Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Pengaturcaraan Serentak C++: Bagaimana Mengenalpasti dan Menyelesaikan Masalah Kebuntuan?

Pengaturcaraan Serentak C++: Bagaimana Mengenalpasti dan Menyelesaikan Masalah Kebuntuan?

WBOY
WBOYasal
2024-05-04 17:54:021147semak imbas

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.

Pengaturcaraan Serentak C++: Bagaimana Mengenalpasti dan Menyelesaikan Masalah Kebuntuan?

Pengaturcaraan Serentak C++: Cara Mengenalpasti dan Menyelesaikan Masalah Kebuntuan

Memahami Deadlock

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:

  • Benang A memegang sumber R1, dan cuba memperoleh sumber R2.
  • Benang B memegang sumber R2 dan cuba mendapatkan sumber R1.

Jika kedua-dua utas memasuki keadaan menunggu pada masa ini, menunggu pihak satu lagi mengeluarkan sumber, kebuntuan akan berlaku.

Kesan jalan buntu

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_guardstd::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;
  }
}

如果在运行此程序时发生死锁,我们会打印错误消息。

解决死锁

一旦检测到死锁,就需要解决它。以下是一些常见的解决方案:

  • 按顺序获取锁:通过强制以特定顺序获取锁(例如,始终先获取 R1,然后获取 R2),可以防止死锁。
  • 使用计时锁:计时锁会在一段时间后超时,迫使线程释放资源。
  • 死锁恢复算法:使用专门的算法,比如银行家算法,可以检测和恢复死锁。

实战案例

考虑以下代码,它在两个线程之间共享一个银行账户对象:

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;
}

如果两个线程同时调用 withdrawdeposit

Kami boleh mengesan kebuntuan dengan menangkap pengecualian ini: 🎜
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: 🎜rrreee

Atas 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!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn