Haruskah saya merawat kondisi balapan yang hampir pasti tidak memiliki peluang terjadi?

52

Mari kita pertimbangkan sesuatu seperti aplikasi GUI di mana utas utama sedang memperbarui UI hampir secara instan, dan beberapa utas lain sedang mengumpulkan data melalui jaringan atau sesuatu yang dijamin akan memakan waktu 5-10 detik untuk menyelesaikan pekerjaan.

Saya telah menerima banyak jawaban berbeda untuk ini, tetapi beberapa orang mengatakan bahwa jika ini adalah kondisi balapan dari ketidakmungkinan statistik, jangan khawatir tentang itu sama sekali tetapi yang lain mengatakan bahwa jika bahkan ada 10 -53 % (saya anak Anda tidak pada angka, ini adalah apa yang saya dengar) dari beberapa sihir voodoo terjadi karena kondisi balapan, selalu mendapatkan / melepaskan kunci pada utas yang membutuhkannya.

Apa yang kamu pikirkan? Apakah ini praktik pemrograman yang baik untuk menangani kondisi lomba dalam situasi yang tidak mungkin secara statistik? atau apakah sama sekali tidak perlu atau bahkan kontraproduktif untuk menambahkan lebih banyak baris kode untuk menghambat keterbacaan?

l46kok
sumber
21
Ketika orang menyatakan peluang seperti itu, mengapa tidak ada yang bertanya tentang pendidikan orang yang menyatakan angka itu? Anda memerlukan pendidikan formal dalam statistik sebelum Anda dapat membuat cadangan dengan angka seperti itu.
Pieter B
27
Sebagai seorang ahli fisika, p <1E-140 berarti p = 0. Tidak akan terjadi di alam semesta ini. 0,0000000000000000000000000000000000000000000000000000001% adalah jauh lebih besar.
MSalters
15
Pastikan kondisi balapan ini tidak dapat menyebabkan seseorang dengan sengaja menabrak aplikasi Anda. Ini bisa menjadi penyebab masalah keamanan.
toasted_flakes
27
Satu dari sejuta peluang terjadi sembilan dari sepuluh.
Kaz Dragon
27
"Hampir pasti tidak ada peluang terjadi?" berarti itu terjadi dalam produksi pada jam 3 pagi dan kemungkinan besar akan sangat mahal.

Jawaban:

137

Jika ini benar-benar peristiwa 1 dalam 10 ^ 55, tidak perlu kode untuk itu. Itu akan menyiratkan bahwa jika Anda melakukan operasi 1 juta kali per detik, Anda akan mendapatkan satu bug setiap 3 * 10 ^ 41 tahun yang, kira-kira, 10 ^ 31 kali usia alam semesta. Jika aplikasi Anda memiliki kesalahan hanya satu kali dalam setiap triliun triliun abad alam semesta, itu mungkin cukup andal.

Namun, saya akan bertaruh sangat besar bahwa kesalahannya hampir tidak mungkin terjadi. Jika Anda dapat memahami kesalahan, hampir pasti bahwa itu akan terjadi setidaknya sesekali sehingga layak untuk dikodekan dengan benar. Plus, jika Anda mengkodekan utas dengan benar di awal sehingga mereka mendapatkan dan melepaskan kunci dengan tepat, kode ini jauh lebih bisa dipelihara di masa depan. Anda tidak perlu khawatir ketika Anda melakukan perubahan bahwa Anda harus menganalisis kembali semua kondisi lomba potensial, menghitung kembali probabilitas mereka, dan meyakinkan diri sendiri bahwa mereka tidak akan terulang kembali.

Gua Justin
sumber
66
Saya teringat akan komentar yang saya baca bertahun-tahun yang lalu tetapi tidak dapat menemukan sekarang "Kesempatan 1 dalam sejuta biasanya Selasa depan". 1 untuk mengatakan itu "tempat dekat yang tidak mungkin".
Bevan
2
+1 untuk taruhan. Cara terbaik untuk menghadapi kondisi balapan adalah dengan menyingkirkannya.
Blrfl
10
@Bevan "Kesempatan 1 dalam sejuta biasanya Selasa depan" ... kecuali jika Anda bermain lotre :)
dasblinkenlight
22
@dasblinkenlight Tetapi peluang seseorang yang menang dalam kebanyakan lotere mendekati 100%. Memprediksi siapa , sekarang itu tantangannya.
Bevan
3
@Bevan: Komentar itu persis apa yang ada dalam pikiran saya ketika saya membaca pertanyaan - di sini adalah referensi: blogs.msdn.com/b/larryosterman/archive/2004/03/30/104165.aspx
Doc Brown
69

Dari sudut pandang biaya-manfaat, Anda harus menulis kode tambahan hanya ketika Anda mendapat manfaat yang cukup.

Misalnya, jika hal terburuk yang akan terjadi jika utas yang salah "memenangkan perlombaan" adalah bahwa informasi tidak akan ditampilkan, dan pengguna perlu mengklik "segarkan", jangan repot-repot menjaga terhadap kondisi balapan: harus menulis banyak kode tidak layak memperbaiki sesuatu yang tidak signifikan.

Di sisi lain, jika kondisi balapan dapat mengakibatkan transfer uang yang salah antar rekening perbankan, maka Anda harus waspada terhadap kondisi balapan, tidak peduli berapa banyak kode yang perlu Anda tulis untuk menyelesaikan masalah ini.

dasblinkenlight
sumber
20
+1: Untuk membuat perbedaan antara "Kegagalan yang terlihat seperti kegagalan" dan "Kegagalan yang terlihat seperti kesuksesan". Informasi yang salah jauh lebih serius, tergantung pada domainnya.
deworde
2
+1 itu membuat perbedaan besar apa hasil dari kondisi balapan bisa.
Berikan
+1 Konsekuensi dari kondisi balapan harus menjadi faktor penentu utama dalam jika harus ditangani. Kondisi lomba yang dapat menyebabkan kecelakaan pesawat jauh berbeda dari kondisi yang mungkin memaksa pengguna untuk membuka kembali aplikasi.
aduk
1
+1: Saya akan mengatakan bahwa konsekuensinya mungkin apa yang harus Anda analisis dan bukan probabilitas itu terjadi. Jika konsekuensinya tidak penting, Anda mungkin tidak perlu menangani kondisi lomba BAHKAN jika itu sangat umum.
Leo
1
Tetapi jangan berasumsi bahwa memperbaiki kondisi balapan secara otomatis berarti Anda harus menulis lebih banyak kode. Mungkin juga berarti menghapus sejumlah besar kode kereta dan menggantinya dengan sepotong kecil kode yang benar.
JesperE
45

Menemukan kondisi balapan adalah bagian yang sulit. Anda mungkin menghabiskan waktu hampir sebanyak menulis pertanyaan ini karena Anda harus memperbaikinya. Ini tidak seperti itu membuatnya menjadi jauh lebih mudah dibaca. Programmer berharap untuk melihat kode sinkronisasi dalam situasi seperti itu, dan benar-benar mungkin membuang lebih waktu bertanya-tanya mengapa itu tidak ada dan jika menambahkan akan memperbaiki bug yang tidak terkait mereka.

Sejauh menyangkut probabilitas, Anda akan terkejut. Saya memiliki laporan bug kondisi ras tahun lalu yang tidak dapat saya buat ulang dengan ribuan percobaan otomatis, tetapi satu sistem dari satu pelanggan melihatnya sepanjang waktu. Nilai bisnis dari menghabiskan 5 menit untuk memperbaikinya sekarang, versus kemungkinan pemecahan masalah bug yang "tidak mungkin" di instalasi pelanggan, membuat pilihan menjadi no-brainer.

Karl Bielefeldt
sumber
1
Ini juga! Hindari meminta programmer lain merenungkan kemungkinan masalah saat membaca kode Anda, dengan melakukan apa yang perlu (bahkan jika 'tidak mungkin' gagal).
Casey Kuball
Poin Anda diambil dengan baik (perbaikan yang dibuat sekarang lebih cepat dan lebih murah daripada yang dibuat nanti) kecuali bahwa itu tidak akan pernah hanya "5 menit untuk memperbaikinya sekarang".
iconoclast
2
+1 untuk menunjukkan bahwa kemungkinan kondisi balapan mungkin tergantung pada banyak faktor, jadi meskipun terlihat tidak mungkin dalam konfigurasi Anda , itu mungkin terjadi lebih sering pada sistem pelanggan / pada OS yang berbeda / dalam rilis berikutnya dll.
sleske
27

Dapatkan dan lepaskan kunci. Probabilitas berubah, algoritma berubah. Ini kebiasaan buruk untuk masuk, dan ketika ada masalah Anda tidak perlu berhenti dan bertanya-tanya apakah Anda salah peluang ...

jmoreno
sumber
6
+1 untuk perubahan algoritma. Saat ini, ketika Anda mengetahui kondisi balapan, probabilitasnya rendah. Setelah satu tahun, ketika Anda lupa tentang kondisi balapan, Anda dapat membuat perubahan pada kode Anda yang secara signifikan mengubah waktu dan kemungkinan bug.
Phil
13

dan beberapa utas lainnya adalah polling data melalui jaringan atau sesuatu yang dijamin akan memakan waktu 5-10 detik untuk menyelesaikan pekerjaan.

Sampai seseorang memperkenalkan lapisan caching untuk meningkatkan kinerja. Tiba-tiba tapak lainnya selesai dekat dan kondisi pacuan kuda bermanifestasi lebih sering daripada tidak.

Seandainya ini terjadi beberapa minggu yang lalu, butuh sekitar 2 hari pengembang penuh untuk menemukan bug.

Selalu perbaiki kondisi balapan jika Anda mengenalinya.

Michael Borgwardt
sumber
8

Sederhana vs benar.

Dalam banyak kasus, kesederhanaan mengalahkan kebenaran. Ini masalah biaya.

Juga, kondisi lomba adalah hal-hal buruk yang cenderung tidak mematuhi statistik sederhana. Semuanya berjalan dengan baik sampai beberapa sinkronisasi lain yang tampaknya tidak berhubungan menyebabkan kondisi balapan Anda tiba-tiba terjadi separuh waktu. Kecuali Anda mengaktifkan log atau men-debug kode saja.

Alternatif pragmatis untuk mencegah kondisi balapan (yang bisa rumit) bisa dengan mendeteksi dan mencatatnya (bonus untuk gagal keras dan awal). Jika itu tidak pernah terjadi, Anda kehilangan sedikit. Jika itu benar-benar terjadi, Anda mendapat justifikasi yang kuat untuk menghabiskan waktu ekstra memperbaikinya.

ptyx
sumber
1
+1 untuk masuk dan gagal lebih awal jika memperbaikinya terlalu rumit.
Martin Ba
Dalam banyak kasus, kesederhanaan mengalahkan kelengkapan. Sinkronisasi hampir tidak pernah ada di antara kasus-kasus itu. Hampir selalu akan kembali menggigit Anda (atau pria malang bertugas menjaga kode Anda) nanti.
reirab
@reirab saya tidak setuju. Jika Anda mempertimbangkan peristiwa yang jarang terjadi, maka kegagalan log adalah efektif biaya. Contoh: jika aplikasi ponsel Anda memiliki tingkat kegagalan 1/100 (macet) jika pengguna beralih jaringan pada transisi bulan yang tepat (1/31 23:59:00 -> 2/1 00:00:00), Anda Mungkin tidak akan pernah mendengarnya. Tapi kemudian 1/10 ^ 9 kemungkinan crash pada koneksi di server tidak dapat diterima. Tergantung.
ptyx
7

Jika kondisi ras Anda terkait dengan keamanan, Anda harus selalu kode untuk mencegahnya.

Contoh umum adalah kondisi balapan dengan membuat / membuka file di unix, yang dalam beberapa keadaan dapat menyebabkan serangan eskalasi hak istimewa jika program dengan kondisi balapan dijalankan dengan hak istimewa yang lebih tinggi daripada pengguna yang berinteraksi dengannya, seperti proses daemon sistem atau lebih buruk lagi, kernel.

Bahkan jika suatu kondisi balapan memiliki kemungkinan 10 ^ (- 80) terjadi secara acak , mungkin saja penyerang yang gigih memiliki kesempatan yang layak untuk menciptakan kondisi seperti itu secara sengaja dan artifisial.

Bristol
sumber
6

Therac-25!

Pengembang pada proyek Therac-25 cukup yakin tentang waktu antara UI dan masalah terkait antarmuka dalam mesin XRAY terapeutik.

Seharusnya tidak.

Anda dapat mempelajari lebih lanjut tentang bencana perangkat lunak hidup dan mati yang terkenal ini di:

http://www.youtube.com/watch?v=izGSOsAGIVQ

atau

http://en.wikipedia.org/wiki/Therac-25

Aplikasi Anda mungkin jauh kurang sensitif terhadap kegagalan daripada perangkat medis. Metode yang bermanfaat adalah menilai paparan risiko sebagai produk dari kemungkinan terjadinya dan biaya kejadian selama masa pakai produk untuk semua unit yang dapat diproduksi.

Jika Anda memilih untuk membuat kode Anda agar bertahan lama (dan sepertinya Anda memilikinya), Anda harus mempertimbangkan hukum Moore yang dapat dengan mudah memotong beberapa nol setiap beberapa tahun karena komputer di dalam atau di luar sistem Anda menjadi lebih cepat. Jika Anda mengirim ribuan salinan, potong lebih banyak nol. Jika pengguna melakukan operasi ini setiap hari (atau bulanan) selama bertahun-tahun, ambil beberapa lagi. Jika digunakan di mana Google fiber tersedia, lalu apa? Jika sampah UI mengumpulkan operasi pertengahan GUI, apakah itu memengaruhi balapan? Apakah Anda menggunakan Open Source atau Windows library di belakang GUI Anda? Bisakah pembaruan di sana memengaruhi waktu?

Semafor, kunci, mutex, sinkronisasi penghalang adalah beberapa cara untuk menyinkronkan aktivitas di antara utas. Berpotensi jika Anda tidak menggunakannya, orang lain yang mengelola program Anda mungkin dan kemudian dengan cepat asumsi tentang hubungan antara utas dapat bergeser dan perhitungan tentang kondisi balapan mungkin tidak valid.

Saya sarankan Anda menyinkronkan secara eksplisit karena meskipun Anda mungkin tidak pernah melihatnya membuat masalah, pelanggan mungkin. Selain itu, bahkan jika kondisi ras Anda tidak pernah terjadi, bagaimana jika Anda atau organisasi Anda dipanggil ke pengadilan untuk mempertahankan kode Anda (seperti yang Toyota lakukan dengan Prius beberapa tahun yang lalu). Semakin teliti metodologi Anda, semakin baik tarif Anda. Mungkin lebih baik untuk mengatakan "kami menjaga terhadap kasus yang tidak mungkin seperti ini ..." daripada mengatakan, "kami tahu kode kami akan gagal, tetapi kami menuliskan persamaan ini untuk menunjukkan bahwa hal itu tidak akan terjadi dalam masa hidup kami. Mungkin. "

Sepertinya perhitungan probabilitas berasal dari orang lain. Apakah mereka tahu kode Anda dan apakah Anda cukup mengenalnya untuk percaya bahwa tidak ada kesalahan yang terjadi? Jika saya menghitung keandalan 99,99997% untuk sesuatu, saya mungkin juga berpikir kembali ke kelas statistik perguruan tinggi saya dan ingat bahwa saya tidak selalu mendapatkan 100%, dan mundur beberapa persen dari perkiraan keandalan pribadi saya sendiri.

Pengembang Don
sumber
1
+1 untuk penyebutan Therac-25. Banyak pelajaran penting di sini.
Stuart Marks
Meskipun saya pikir ini adalah jawaban yang baik, Anda bisa berargumen bahwa proyek GUI hobi Anda pasti tidak akan menyebabkan orang mati jika Anda gagal menghilangkan kondisi ras.
marktani
Saya tidak banyak berdebat, tetapi jika saya, saya mungkin berdebat bahwa setiap kali kita menulis kode kita harus menuliskannya dengan benar. Jika kita dapat berlatih mengeluarkan persyaratan lomba dari proyek hobi kita di mana kode lebih sederhana dan mungkin kita satu-satunya penulis, kita akan jauh lebih siap ketika kita menangani proyek kerja di mana pekerjaan beberapa penulis perlu diintegrasikan bersama.
DeveloperDon
4

apakah sama sekali tidak perlu atau bahkan kontraproduktif untuk menambahkan lebih banyak baris kode untuk menghambat keterbacaan?

Kesederhanaan hanya baik ketika itu juga benar. Karena kode ini tidak benar, programmer masa depan pasti akan melihatnya ketika mencari bug terkait.

Apa pun cara Anda menanganinya (baik dengan mencatatnya, mendokumentasikannya, atau menambahkan kunci - ini tergantung pada biaya), Anda akan menghemat waktu programmer lain ketika melihat kode.

Casey Kuball
sumber
3

Ini akan tergantung pada konteksnya. Jika ini adalah permainan iPhone biasa, mungkin tidak. Sistem kontrol penerbangan untuk kendaraan luar angkasa berawak berikutnya, mungkin. Itu semua tergantung pada apa konsekuensinya jika hasil 'buruk' terjadi diukur terhadap perkiraan biaya untuk memperbaikinya.

Jarang ada jawaban 'satu ukuran cocok untuk semua' untuk jenis pertanyaan ini karena mereka bukan pertanyaan pemrograman, melainkan pertanyaan ekonomi.

GrandmasterB
sumber
3
"Sistem kontrol penerbangan untuk kendaraan luar angkasa berawak berikutnya" PASTI .
deworde
mungkin ... pasti ... itu tergantung pada siapa yang ada di roket :-)
GrandmasterB
3

Ya, harapkan yang tidak terduga. Saya telah menghabiskan berjam-jam (dalam kode orang lain ^^) melacak kondisi yang seharusnya tidak pernah terjadi.

Hal-hal seperti selalu memiliki yang lain, selalu memiliki kasus bawaan, menginisialisasi variabel (ya, benar-benar .. bug terjadi dari ini), periksa loop Anda untuk variabel yang digunakan kembali untuk setiap iterasi, dll.

Jika Anda khawatir tentang masalah threading secara spesifik, baca blog, artikel, dan buku tentang subjek tersebut. Tema saat ini tampaknya merupakan data yang tidak berubah.

Paul
sumber
3

Perbaiki saja.

Saya sudah melihat ini persis. Satu utas berhasil membuat permintaan jaringan ke server yang melakukan pencarian basis data yang kompleks dan merespons sebelum utas lainnya sampai ke baris kode berikutnya. Itu terjadi.

Beberapa pelanggan di suatu tempat akan memutuskan suatu hari untuk menjalankan sesuatu yang memakan semua waktu CPU untuk utas "cepat" sambil membiarkan utas lambat berjalan, dan Anda akan menyesal :)

JohnB
sumber
1

Jika Anda mengenali kondisi balapan yang tidak biasa, setidaknya dokumentasikan dalam kode!

EDIT: Saya harus menambahkan bahwa saya akan memperbaikinya jika memungkinkan, tetapi pada saat menulis di atas tidak ada jawaban lain yang secara eksplisit mengatakan setidaknya mendokumentasikan masalah dalam kode.

Mark Hurd
sumber
1
Yap, dan setidaknya coba dan deteksi dan catat jika itu terjadi. IMHO tidak apa-apa untuk menghindari setiap kesalahan. Tetapi setidaknya beri tahu seseorang bahwa itu terjadi, dan anggapan Anda bahwa itu tidak akan salah arah.
Steve Bennett
0

Saya berpikir bahwa jika Anda sudah tahu bagaimana dan mengapa itu bisa terjadi, mungkin juga menanganinya. Itu jika tidak memakan banyak sumber daya.

Sjaak van der Heide
sumber
0

Itu semua tergantung pada apa konsekuensi dari kondisi balapan. Saya pikir orang-orang yang menjawab pertanyaan Anda benar untuk pekerjaan mereka. Milik saya adalah mesin konfigurasi router. Bagi saya, kondisi balapan membuat sistem diam, rusak atau tidak terkonfigurasi walaupun dikatakan berhasil. Saya selalu menggunakan semaphores per router sehingga saya tidak perlu membersihkan apa pun dengan tangan.

Saya pikir beberapa kode GUI saya masih rentan terhadap kondisi balapan sedemikian rupa sehingga pengguna dapat diberikan kesalahan karena kondisi balapan terjadi, tetapi saya tidak akan memiliki kemungkinan seperti itu jika ada kemungkinan korupsi data atau perilaku yang salah dari pengguna. aplikasi setelah acara tersebut.

Sylwester
sumber
0

Lucunya, saya mengalami masalah ini baru-baru ini. Aku bahkan tidak menyadari kondisi ras mungkin terjadi dalam keadaanku. Kondisi balapan hanya muncul dengan sendirinya ketika prosesor multi-core menjadi norma.

Skenario kira-kira seperti ini. Driver perangkat mengangkat peristiwa untuk ditangani oleh perangkat lunak. Kontrol harus kembali ke driver perangkat sesegera mungkin untuk mencegah batas waktu pada perangkat. Untuk memastikan ini, acara direkam dan diantrekan di utas terpisah.

Receive event from device:
{
    Record event details.
    Enqueue event in the queuing thread.
    Acknowledge the event.
}

Queueing thread receives an event:
{
    Retrieve event details.
    Process event.
    Send next command to device.
}

Ini bekerja dengan baik selama bertahun-tahun. Kemudian tiba-tiba akan gagal dalam konfigurasi tertentu. Ternyata utas antrian sekarang berjalan benar-benar sejajar dengan utas penanganan acara, daripada berbagi waktu prosesor tunggal. Itu berhasil mengirim perintah berikutnya ke perangkat sebelum acara telah diakui, menyebabkan kesalahan di luar urutan.

Mengingat itu hanya mempengaruhi satu pelanggan dalam satu konfigurasi, saya memalukan Thread.Sleep(1000)di mana masalahnya. Tidak ada masalah sejak itu.

Makanan Tangan
sumber