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?
Jawaban:
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.
sumber
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.
sumber
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.
sumber
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 ...
sumber
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.
sumber
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.
sumber
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.
sumber
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.
sumber
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.
sumber
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.
sumber
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.
sumber
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 :)
sumber
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.
sumber
Saya berpikir bahwa jika Anda sudah tahu bagaimana dan mengapa itu bisa terjadi, mungkin juga menanganinya. Itu jika tidak memakan banyak sumber daya.
sumber
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.
sumber
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.
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.sumber