Rumah > Artikel > pembangunan bahagian belakang > Pengaturcaraan Serentak C++: Bagaimana Mengenalpasti dan Menyelesaikan Masalah Kebuntuan?
Dalam pengaturcaraan serentak C++, masalah kebuntuan berlaku apabila satu atau lebih utas menunggu selama-lamanya untuk utas lain mengeluarkan sumber, menyebabkan atur cara digantung. Kita boleh menggunakan std::lock_guard dan std::unique_lock untuk melaksanakan pengesanan jalan buntu Jika kebuntuan berlaku, pengecualian std::system_error akan dilemparkan. Kaedah untuk menyelesaikan kebuntuan termasuk memperoleh kunci mengikut tertib, menggunakan kunci bermasa dan algoritma pemulihan kebuntuan.
Kebuntuan ialah ralat biasa dalam pengaturcaraan serentak yang berlaku apabila satu atau lebih utas menunggu selama-lamanya untuk dikeluarkan oleh sumber benang lain. Situasi ini menyebabkan program itu tergantung selama-lamanya.
Untuk memahami kebuntuan, pertimbangkan senario berikut:
Jika kedua-dua utas memasuki keadaan menunggu pada masa ini, menunggu pihak satu lagi mengeluarkan sumber, kebuntuan akan berlaku.
Dalam C++, kami boleh menggunakan kunci seperti std::lock_guard
dan std::unique_lock
untuk melindungi sumber. Kunci ini melaksanakan mekanisme pengesanan jalan buntu dan jika jalan buntu dikesan, pengecualian std::system_error
akan dilemparkan. std::lock_guard
和 std::unique_lock
这样的锁保护资源。这些锁实现了死锁检测机制,如果检测到死锁,会抛出 std::system_error
异常。
我们可以通过捕捉此异常来检测死锁:
std::mutex m1; std::mutex m2; void foo() { // 获取锁 std::lock_guard<std::mutex> lock1(m1); std::lock_guard<std::mutex> lock2(m2); // 其他操作... }
int main() { try { foo(); } catch (const std::system_error& e) { std::cerr << "死锁检测到:异常代码 " << e.code() << std::endl; } }
如果在运行此程序时发生死锁,我们会打印错误消息。
一旦检测到死锁,就需要解决它。以下是一些常见的解决方案:
考虑以下代码,它在两个线程之间共享一个银行账户对象:
class BankAccount { public: int balance; std::mutex m; }; void withdraw(BankAccount& account, int amount) { std::lock_guard<std::mutex> lock(account.m); if (account.balance >= amount) account.balance -= amount; } void deposit(BankAccount& account, int amount) { std::lock_guard<std::mutex> lock(account.m); account.balance += amount; }
如果两个线程同时调用 withdraw
和 deposit
void withdraw(BankAccount& account, int amount) { std::lock_guard<std::mutex> lock(account.m); if (account.balance >= amount) account.balance -= amount; } void deposit(BankAccount& account, int amount) { std::lock_guard<std::mutex> lock(account.m); account.balance += amount; }rrreee🎜Jika kebuntuan berlaku semasa menjalankan program ini, kami mencetak mesej ralat. 🎜🎜Menyelesaikan Kebuntuan🎜🎜Setelah kebuntuan dikesan, ia perlu diselesaikan. Berikut ialah beberapa penyelesaian biasa: 🎜🎜🎜Peroleh kunci mengikut urutan: Kebuntuan boleh dielakkan dengan memaksa kunci diperoleh dalam susunan tertentu (contohnya, sentiasa memperoleh R1 dahulu, kemudian R2). 🎜🎜Gunakan kunci pemasaan: Kunci pemasaan akan tamat masa selepas satu tempoh masa, memaksa urutan mengeluarkan sumber. 🎜🎜Algoritma Pemulihan Kebuntuan: Kebuntuan boleh dikesan dan dipulihkan menggunakan algoritma khusus, seperti Algoritma Jurubank. 🎜🎜🎜Kes praktikal🎜🎜Pertimbangkan kod berikut, yang berkongsi objek akaun bank antara dua urutan: 🎜rrreee🎜Jika dua utas memanggil
tarik
dan deposit
pada masa yang sama fungsi, kebuntuan mungkin berlaku. Kita boleh menyelesaikan masalah ini dengan mendapatkan kunci mengikut urutan: 🎜rrreeeAtas ialah kandungan terperinci Pengaturcaraan Serentak C++: Bagaimana Mengenalpasti dan Menyelesaikan Masalah Kebuntuan?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!