我是线程的新手,正在尝试了解互斥体。
我将互斥体理解为仅由一个线程选取的某个对象(键)(如果它被选取,则其他线程无法选取它并且必须等待)才能访问我们要锁定的部分代码。
所以当时只有一个线程可以访问代码的锁定部分(例如共享计数器)。其他线程必须等到互斥体解锁等等。
Mutex1.Lock();
{
Mutex2.Lock();
{
// Code locked by mutex 1 and 2.
}
Mutex2.Unlock();
// Code locked by mutex 1.
}
Mutex1.Unlock();
如果我写多个互斥锁会怎样?
两个互斥锁会被同一个线程选中吗?我还读到多个互斥锁可能会导致死锁。
谁能解释并提供一个示例,说明我如何通过使用 2 个互斥锁锁定部分代码来导致死锁?
最佳答案
这是对您描述的内容进行编码的安全方法:
std::mutex Mutex1;
std::mutex Mutex2;
void
test()
{
using namespace std;
lock(Mutex1, Mutex2); // no deadlock!
lock_guard<mutex> lk1{Mutex1, adopt_lock};
{
lock_guard<mutex> lk2{Mutex2, adopt_lock};
// Code locked by mutex 1 and 2.
} // lk2.unlock()
// Code locked by mutex 1.
} // lk1.unlock()
这段代码不会死锁,因为 std::lock(Mutex1, Mutex2)
锁定了两个互斥锁,同时避免了死锁(通过一些内部算法)。使用 std::lock
的一个优点是您不必记住锁定互斥量所需的顺序(这使得大型代码库中的维护更容易)。但缺点是您需要在代码中的单个点上同时锁定两个锁。如果您不能同时锁定它们,那么您必须回到其他答案所描述的顺序。
这段代码也是异常安全的,因为如果在任何地方抛出任何异常,当异常传播出去时,任何碰巧被锁定的东西都会被解锁。
关于c++ - 具有互斥量的多个锁和死锁的可能性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42720131/