Tentunya, banyak yang mendengar, tetapi seseorang bertemu dalam latihan, kata-kata seperti deadlock dan kondisi ras. Konsep-konsep ini diklasifikasikan sebagai kesalahan dalam penggunaan konkurensi. Jika saya bertanya kepada Anda tentang apa yang disebut deadlock, Anda sangat mungkin mulai menggambar deadlock klasik atau perwakilannya dalam pseudo-code tanpa keraguan. Sesuatu seperti ini:

Kami mendapatkan informasi ini di institut, dapat ditemukan di buku dan artikel di Internet. Kebuntuan seperti itu menggunakan, misalnya, dua mutex, dalam semua kemuliaan dapat ditemukan dalam kode. Tetapi dalam kebanyakan kasus, tidak semuanya begitu sederhana, dan tidak semua orang dapat melihat pola kesalahan klasik dalam kode jika tidak disajikan dalam bentuk biasa.

Pertimbangkan kelas yang kami minati dalam metode StartUpdate, CheckAndUpdate, dan Stop, C ++ digunakan, kode ini sesederhana mungkin:
std::recursive_mutex m_mutex; Future m_future; void Stop() { std::unique_lock scoped_lock(m_mutex); m_future.Wait();
Apa yang harus Anda perhatikan dalam kode yang disajikan:
- mutex rekursif digunakan. Pengambilan berulang dari mutex rekursif tidak mengarah pada harapan hanya jika penangkapan ini terjadi di utas yang sama. Dalam hal ini, jumlah pengecualian mutex harus sesuai dengan jumlah tangkapan. Jika kami mencoba untuk menangkap mutex rekursif yang sudah ditangkap di utas lain, utas masuk ke mode siaga.
- Masa Depan :: Fungsi jadwal dimulai (dalam n milidetik) di utas terpisah yang dilewati panggilan balik kepadanya
Sekarang kami menganalisis semua informasi yang diterima dan membuat gambar:

Mempertimbangkan dua fakta yang disajikan di atas, tidak sulit untuk menyimpulkan bahwa upaya untuk menangkap mutasi rekursif di salah satu fungsi akan mengarah pada ekspektasi akan pelepasan mutex jika sudah ditangkap di fungsi lain, karena panggilan balik CheckAndUpdate selalu dieksekusi di utas terpisah.
Sekilas, tidak ada yang mencurigakan terkait kebuntuan. Tetapi untuk lebih dekat, semuanya bermuara pada gambaran klasik kita. Ketika objek fungsional mulai dijalankan, kami secara implisit menangkap sumber daya m_future, panggilan balik secara langsung
terkait dengan m_future:
Urutan tindakan yang mengarah ke kebuntuan adalah sebagai berikut:- Direncanakan untuk menjalankan CheckAndUpdate, tetapi panggilan balik tidak dimulai segera, setelah n milidetik.
- Metode Stop dipanggil, dan kemudian dimulai: kami mencoba untuk menangkap mutex - sumber daya adalah satu ditangkap, kami mulai menunggu untuk menyelesaikan m_future - objek belum dipanggil, kami sedang menunggu.
- Eksekusi dari CheckAndUpdate dimulai: kami mencoba menangkap mutex - kami tidak bisa, sumber dayanya sudah ditangkap oleh utas lain, kami menunggu rilis.
Itu saja: utas yang membuat Stop call menunggu untuk CheckAndUpdate selesai, dan utas lainnya, pada gilirannya, tidak dapat terus bekerja sampai ia mengambil mutex yang telah ditangkap oleh utas yang disebutkan sebelumnya. Jalan buntu klasik. Setengah pekerjaan selesai - penyebab masalah telah ditemukan.
Sekarang sedikit tentang cara memperbaikinya.Pendekatan 1Prosedur untuk mengambil sumber daya harus sama, ini akan menghindari kebuntuan. Artinya, Anda perlu melihat apakah mungkin untuk mengubah urutan penangkapan sumber daya dalam metode Stop. Karena di sini kasus kebuntuan tidak sepenuhnya jelas, dan tidak ada penangkapan eksplisit sumber daya m_future di CheckAndUpdate, kami memutuskan untuk memikirkan solusi lain untuk menghindari pengembalian kesalahan di masa mendatang.
Pendekatan 2- Periksa apakah Anda dapat memilih tidak menggunakan mutex di CheckAndUpdate.
- Karena kami menggunakan mekanisme sinkronisasi, kami membatasi akses ke beberapa sumber. Mungkin itu akan cukup bagi Anda untuk membuat kembali sumber daya ini menjadi atom (seperti yang kita miliki), akses yang sudah aman-thread.
- Ternyata variabel, akses yang terbatas, dapat dengan mudah dikonversi ke atom, sehingga mutex yang disebutkan berhasil dihapus.
Berikut adalah contoh langsung dengan kebuntuan yang tidak terlihat yang dengan mudah mengurangi pola kesalahan ini. Akhirnya, saya ingin Anda menulis kode yang dapat diandalkan dan aman!