Saat menulis aplikasi multithreaded, salah satu masalah paling umum yang dialami adalah kondisi ras.
Pertanyaan saya kepada komunitas adalah:
Bagaimana kondisi lomba?
Bagaimana Anda mendeteksi mereka?
Bagaimana Anda menanganinya?
Akhirnya, bagaimana Anda mencegahnya terjadi?
multithreading
concurrency
terminology
race-condition
bmurphy1976
sumber
sumber
Jawaban:
Kondisi ras terjadi ketika dua utas atau lebih dapat mengakses data yang dibagikan dan mereka mencoba mengubahnya pada saat yang sama. Karena algoritme penjadwalan utas dapat bertukar antar utas kapan saja, Anda tidak tahu urutan upaya utas untuk mengakses data yang dibagikan. Oleh karena itu, hasil dari perubahan dalam data tergantung pada algoritma penjadwalan thread, yaitu kedua thread "balap" untuk mengakses / mengubah data.
Masalah sering terjadi ketika satu utas melakukan "centang-lalu-bertindak" (mis. "Centang" jika nilainya X, lalu "bertindak" untuk melakukan sesuatu yang bergantung pada nilai menjadi X) dan utas lainnya melakukan sesuatu terhadap nilai di antara tanda "check" dan "act". Misalnya:
Intinya, y bisa 10, atau bisa apa saja, tergantung pada apakah utas lain berubah x di antara pemeriksaan dan tindakan. Anda tidak memiliki cara nyata untuk mengetahui.
Untuk mencegah terjadinya kondisi balapan, Anda biasanya akan mengunci di sekitar data yang dibagikan untuk memastikan hanya satu utas yang dapat mengakses data pada suatu waktu. Ini akan berarti sesuatu seperti ini:
sumber
"Kondisi ras" ada ketika kode multithreaded (atau paralel) yang akan mengakses sumber daya bersama bisa melakukannya sedemikian rupa sehingga menyebabkan hasil yang tidak terduga.
Ambil contoh ini:
Jika Anda memiliki 5 utas yang mengeksekusi kode ini sekaligus, nilai x TIDAK AKAN berakhir menjadi 50.000.000. Itu sebenarnya akan bervariasi dengan setiap lari.
Ini karena, agar setiap untaian menambah nilai x, mereka harus melakukan hal berikut: (disederhanakan, jelas)
Setiap utas dapat pada setiap langkah dalam proses ini kapan saja, dan mereka dapat saling menginjak ketika sumber daya bersama dilibatkan. Keadaan x dapat diubah oleh utas lainnya selama waktu antara x sedang dibaca dan ketika itu ditulis kembali.
Katakanlah utas mengambil nilai x, tetapi belum menyimpannya. Thread lain juga dapat mengambil yang sama nilai x (karena tidak ada benang telah berubah itu belum) dan kemudian mereka berdua akan menyimpan sama nilai (x + 1) kembali x!
Contoh:
Kondisi lomba dapat dihindari dengan menggunakan semacam mekanisme penguncian sebelum kode yang mengakses sumber daya bersama:
Di sini, jawabannya muncul 50.000.000 setiap kali.
Untuk lebih lanjut tentang penguncian, cari: mutex, semaphore, bagian kritis, sumber daya bersama.
sumber
Anda berencana menonton film pada jam 5 sore. Anda menanyakan tentang ketersediaan tiket pada jam 4 sore. Perwakilan mengatakan bahwa mereka tersedia. Anda bersantai dan mencapai jendela tiket 5 menit sebelum pertunjukan. Saya yakin Anda bisa menebak apa yang terjadi: ini adalah rumah yang penuh. Masalahnya di sini adalah durasi antara cek dan tindakan. Anda bertanya pada 4 dan bertindak pada 5. Sementara itu, orang lain mengambil tiket. Itu adalah kondisi balapan - khususnya skenario "periksa-lalu-bertindak" kondisi lomba.
Ulasan kode agama, tes unit multi-utas. Tidak ada jalan pintas. Ada beberapa plugin Eclipse yang muncul pada ini, tetapi belum ada yang stabil.
Hal terbaik adalah membuat fungsi efek stateless dan bebas efek samping, gunakan immutables sebanyak mungkin. Tetapi itu tidak selalu mungkin. Jadi menggunakan java.util.concurrent.atomic, struktur data bersamaan, sinkronisasi yang tepat, dan concurrency berbasis aktor akan membantu.
Sumber daya terbaik untuk konkurensi adalah JCIP. Anda juga bisa mendapatkan detail lebih lanjut tentang penjelasan di atas di sini .
sumber
Ada perbedaan teknis yang penting antara kondisi balapan dan ras data. Sebagian besar jawaban tampaknya membuat asumsi bahwa istilah-istilah ini setara, tetapi tidak.
Perlombaan data terjadi ketika 2 instruksi mengakses lokasi memori yang sama, setidaknya salah satu dari akses ini adalah tulis dan tidak ada yang terjadi sebelum memesan di antara akses ini. Sekarang apa yang membentuk suatu terjadi sebelum memesan tunduk pada banyak perdebatan, tetapi secara umum pasangan kunci-ulock pada variabel kunci yang sama dan pasangan sinyal-tunggu pada variabel kondisi yang sama menginduksi order terjadi sebelum pesanan.
Kondisi balapan adalah kesalahan semantik. Ini adalah cacat yang terjadi dalam waktu atau urutan peristiwa yang mengarah pada perilaku program yang salah .
Banyak kondisi lomba dapat (dan faktanya) disebabkan oleh perlombaan data, tetapi ini tidak perlu. Sebagai soal fakta, data ras dan kondisi ras tidak diperlukan, atau kondisi yang cukup untuk satu sama lain. Posting blog ini juga menjelaskan perbedaannya dengan sangat baik, dengan contoh transaksi bank sederhana. Berikut adalah contoh sederhana lain yang menjelaskan perbedaannya.
Sekarang setelah kita memahami terminologi, mari kita coba menjawab pertanyaan aslinya.
Mengingat bahwa kondisi ras adalah bug semantik, tidak ada cara umum untuk mendeteksi mereka. Ini karena tidak ada cara untuk memiliki oracle otomatis yang dapat membedakan perilaku program yang benar dan yang salah dalam kasus umum. Deteksi ras merupakan masalah yang tidak dapat dipastikan.
Di sisi lain, ras data memiliki definisi yang tepat yang tidak selalu berhubungan dengan kebenaran, dan karenanya seseorang dapat mendeteksinya. Ada banyak rasa pendeteksi ras data (deteksi ras data statis / dinamis, deteksi ras data berbasis-lockset, yang terjadi sebelum deteksi ras data, deteksi ras data hybrid). Detektor ras data dinamis canggih adalah ThreadSanitizer yang bekerja sangat baik dalam praktiknya.
Menangani perlombaan data secara umum membutuhkan beberapa disiplin pemrograman untuk mendorong terjadi sebelum tepi antara akses ke data bersama (baik selama pengembangan, atau sekali mereka terdeteksi menggunakan alat yang disebutkan di atas). ini dapat dilakukan melalui kunci, variabel kondisi, semaphore, dll. Namun, kita juga dapat menggunakan paradigma pemrograman yang berbeda seperti passing pesan (bukan memori bersama) yang menghindari perlombaan data oleh konstruksi.
sumber
Definisi semacam kanonik adalah " ketika dua utas mengakses lokasi yang sama di memori pada saat yang sama, dan setidaknya salah satu akses adalah sebuah tulisan ." Dalam situasi ini, utas "pembaca" mungkin mendapatkan nilai lama atau nilai baru, tergantung pada utas mana yang "memenangkan perlombaan." Ini tidak selalu bug — pada kenyataannya, beberapa algoritma level rendah yang sangat berbulu melakukan ini dengan sengaja — tetapi umumnya harus dihindari. @Steve Gury memberikan contoh yang baik tentang kapan itu mungkin menjadi masalah.
sumber
Kondisi ras adalah sejenis bug, yang hanya terjadi pada kondisi temporal tertentu.
Contoh: Bayangkan Anda memiliki dua utas, A dan B.
Di Thread A:
Di Thread B:
Jika utas A dipraih sesaat setelah memeriksa objek itu. A bukan nol, B akan melakukannya
a = 0
, dan ketika utas A akan mendapatkan prosesor, ia akan melakukan "bagi dengan nol".Bug ini hanya terjadi ketika utas A ditangguhkan tepat setelah pernyataan if, itu sangat jarang, tetapi itu bisa terjadi.
sumber
Kondisi ras tidak hanya terkait dengan perangkat lunak tetapi juga terkait dengan perangkat keras juga. Sebenarnya istilah ini awalnya diciptakan oleh industri perangkat keras.
Menurut wikipedia :
Industri perangkat lunak menggunakan istilah ini tanpa modifikasi, yang membuatnya sedikit sulit untuk dipahami.
Anda perlu melakukan beberapa penggantian untuk memetakannya ke dunia perangkat lunak:
Jadi kondisi balapan dalam industri perangkat lunak berarti "dua utas" / "dua proses" berlomba satu sama lain untuk "mempengaruhi beberapa keadaan bersama", dan hasil akhir dari keadaan bersama akan tergantung pada beberapa perbedaan waktu yang halus, yang dapat disebabkan oleh beberapa spesifik urutan peluncuran thread / proses, penjadwalan thread / proses, dll.
sumber
Kondisi lomba adalah situasi pada pemrograman konkuren di mana dua utas atau proses bersamaan bersaing untuk mendapatkan sumber daya dan kondisi akhir yang dihasilkan tergantung pada siapa yang mendapatkan sumber daya terlebih dahulu.
sumber
Kondisi balapan terjadi dalam aplikasi multi-utas atau sistem multi-proses. Suatu kondisi balapan, pada dasarnya, adalah segala sesuatu yang membuat asumsi bahwa dua hal yang tidak berada dalam urutan atau proses yang sama akan terjadi dalam urutan tertentu, tanpa mengambil langkah-langkah untuk memastikannya. Ini terjadi secara umum ketika dua utas menyampaikan pesan dengan mengatur dan memeriksa variabel anggota kelas yang keduanya dapat akses. Hampir selalu ada kondisi lomba ketika satu utas memanggil tidur untuk memberikan utas lain waktu untuk menyelesaikan tugas (kecuali jika tidur itu dalam satu lingkaran, dengan beberapa mekanisme pemeriksaan).
Alat untuk mencegah kondisi balapan tergantung pada bahasa dan OS, tetapi beberapa yang umum adalah mutex, bagian kritis, dan sinyal. Mutex bagus ketika Anda ingin memastikan bahwa hanya Anda yang melakukan sesuatu. Sinyal baik ketika Anda ingin memastikan orang lain selesai melakukan sesuatu. Meminimalkan sumber daya bersama juga dapat membantu mencegah perilaku tak terduga
Mendeteksi kondisi ras bisa sulit, tetapi ada beberapa tanda. Kode yang sangat bergantung pada tidur cenderung pada kondisi balapan, jadi pertama-tama periksa panggilan untuk tidur dalam kode yang terpengaruh. Menambahkan tidur yang sangat panjang juga dapat digunakan untuk debugging untuk mencoba dan memaksakan urutan peristiwa tertentu. Ini dapat berguna untuk mereproduksi perilaku, melihat apakah Anda dapat menghilangkannya dengan mengubah pengaturan waktu, dan untuk menguji solusi. Tidur harus dihapus setelah debugging.
Tanda tangan bahwa seseorang memiliki kondisi balapan, adalah jika ada masalah yang hanya terjadi sebentar-sebentar pada beberapa mesin. Bug yang umum adalah crash dan deadlock. Dengan logging, Anda harus dapat menemukan area yang terkena dampak dan bekerja kembali dari sana.
sumber
Microsoft sebenarnya telah menerbitkan artikel yang sangat terperinci tentang masalah kondisi dan kebuntuan ini. Abstrak yang paling diringkas darinya adalah paragraf judul:
sumber
Situasi ketika proses sangat tergantung pada urutan atau waktu kejadian lainnya.
Sebagai contoh, Prosesor A dan prosesor B keduanya membutuhkan sumber daya yang identik untuk pelaksanaannya.
Ada alat untuk mendeteksi kondisi balapan secara otomatis:
Kondisi ras dapat ditangani oleh Mutex atau Semaphores . Mereka bertindak sebagai kunci memungkinkan suatu proses untuk memperoleh sumber daya berdasarkan persyaratan tertentu untuk mencegah kondisi balapan.
Ada berbagai cara untuk mencegah kondisi balapan, seperti Critical Section Avoidance .
sumber
Kondisi balapan adalah situasi yang tidak diinginkan yang terjadi ketika perangkat atau sistem mencoba untuk melakukan dua atau lebih operasi pada saat yang sama, tetapi karena sifat perangkat atau sistem, operasi harus dilakukan dalam urutan yang tepat untuk menjadi dilakukan dengan benar.
Dalam memori atau penyimpanan komputer, kondisi balapan dapat terjadi jika perintah untuk membaca dan menulis sejumlah besar data diterima pada saat yang hampir bersamaan, dan mesin berusaha untuk menimpa sebagian atau semua data lama saat data lama masih sedang digunakan. Baca. Hasilnya mungkin satu atau lebih dari yang berikut: komputer crash, "operasi ilegal," pemberitahuan dan penutupan program, kesalahan membaca data lama, atau kesalahan menulis data baru.
sumber
Berikut adalah contoh Saldo Rekening Bank klasik yang akan membantu pemula memahami Thread di Jawa dengan mudah dalam kondisi balapan:
sumber
Anda dapat mencegah kondisi balapan , jika Anda menggunakan kelas "Atom". Alasannya hanyalah utas tidak memisahkan dan mengatur operasi, contohnya di bawah ini:
Akibatnya, Anda akan memiliki 7 tautan "ai". Meskipun Anda melakukan dua tindakan, tetapi operasi kedua mengkonfirmasi utas yang sama dan tidak ada utas lain yang akan mengganggu ini, itu berarti tidak ada kondisi balapan!
sumber
Cobalah contoh dasar ini untuk pemahaman yang lebih baik tentang kondisi balapan:
sumber
Anda tidak selalu ingin membuang kondisi balapan. Jika Anda memiliki bendera yang dapat dibaca dan ditulis oleh banyak utas, dan bendera ini disetel ke 'selesai' oleh satu utas sehingga utas lainnya berhenti diproses saat bendera ditetapkan ke 'selesai', Anda tidak ingin itu "berlomba kondisi "harus dihilangkan. Bahkan, yang ini bisa disebut sebagai kondisi balapan yang jinak.
Namun, dengan menggunakan alat untuk mendeteksi kondisi balapan, itu akan terlihat sebagai kondisi balapan yang berbahaya.
Lebih detail tentang kondisi balapan di sini, http://msdn.microsoft.com/en-us/magazine/cc546569.aspx .
sumber
Pertimbangkan operasi yang harus menampilkan penghitungan segera setelah penghitungan bertambah. mis., segera setelah CounterThread menambah nilai DisplayThread perlu menampilkan nilai yang baru-baru ini diperbarui.
Keluaran
Di sini CounterThread sering mendapatkan kunci dan memperbarui nilai sebelum DisplayThread menampilkannya. Di sini ada kondisi Balapan. Kondisi Balapan dapat diselesaikan dengan menggunakan Sinkronisasi
sumber
Kondisi ras adalah situasi yang tidak diinginkan yang terjadi ketika dua atau lebih proses dapat mengakses dan mengubah data bersama pada saat yang sama. Itu terjadi karena ada akses yang saling bertentangan ke sumber daya. Masalah bagian kritis dapat menyebabkan kondisi balapan. Untuk mengatasi kondisi kritis di antara proses, kami hanya mengambil satu proses pada satu waktu yang menjalankan bagian kritis.
sumber