c++ - 此代码段中是否会发生死锁,为什么?
问题描述
以下代码片段中是否可能出现死锁:
void f()
{
{
std::lock_guard <std::mutex> inner (lock1);
// do something and conditionally return
}
std::lock_guard <std::mutex> outer (lock2);
// do something
}
IOW,如果多个线程调用这个函数,会发生死锁吗?
我不太确定,所以任何帮助将不胜感激。
解决方案
如果你重构你的代码,使每个范围都是一个函数,那么很明显锁永远不会被单个线程同时锁定:
std::mutex lock1;
std::mutex lock2;
// One mutex in g => No deadlock possible
void g()
{
std::lock_guard <std::mutex> inner (lock1);
// do something
}
// One mutex in h => No deadlock possible
void h()
{
std::lock_guard <std::mutex> outer (lock2);
// do something
}
// No mutex in f => No deadlock possible
void f()
{
g();
h();
}
由此您可以得出结论,当线程正在请求锁时,它不会持有锁。这使得死锁是不可能的。您可以通过创建一个简单地包装并添加跟踪的BasicLockable对象来自行检查:std::mutex
class PrinterMutex {
public:
PrinterMutex(const std::string& _name) : name(_name) {}
~PrinterMutex() {}
void lock() {
std::cout << "lock : " << name << std::endl;
m.lock();
}
void unlock() {
std::cout << "unlock : " << name << std::endl;
m.unlock();
}
private:
std::mutex m;
std::string name;
};
PrinterMutex lock1("lock1");
PrinterMutex lock2("lock2");
int main()
{
{
std::lock_guard <PrinterMutex> inner (lock1);
// do something and conditionally return
}
std::lock_guard <PrinterMutex> outer (lock2);
// do something
}
跟踪会告诉你,一个线程总是在请求一个锁之前释放一个锁,这使得死锁是不可能的。
如果您的代码中确实需要多个互斥锁,则应使用std::lock
多个 Lockable 对象来通过死锁避免算法锁定互斥锁。
std::mutex lock1;
std::mutex lock2;
void g()
{
std::lock(lock1, lock2);
std::lock_guard<std::mutex> inner (lock1, std::adopt_lock);
std::lock_guard<std::mutex> outer (lock2, std::adopt_lock);
// Do something
}
推荐阅读
- java - 动态添加行到表格 - Easytable (PDFBox)
- python - 在“for”循环中列出附加问题
- python-3.x - Pandas:按数据框行索引的前两个字符分组
- qt - Qt Multi-Thread Queued Connection Signal / Slot 问题(SLOT 不触发)
- html - 容器上的 Flex 方向和 flex wrap 会在 flex-item 中产生额外的空间
- stata - 如何在Stata中重新编码范围内的缺失值
- minitest - guard-minitest 运行所有测试,而不仅仅是目标文件更改的测试
- vuejs2 - 无法从 Vue 数据中获取正确的数据
- python - 使用 buildozer 编译时找不到 mpmath
- python - 未能创建数据框并将其数据正确填充到 csv 文件中