具有互斥锁的多个锁和可能发生死锁

sti*_*far 6 c c++ multithreading mutex pthreads

我是线程新手并试图理解互斥锁.
我理解互斥锁是一个只被一个线程挑选的对象(密钥)(如果它被挑选然后其他线程无法选择它并且必须等待)来访问我们想要锁定的代码的某些部分.
因此,当时只有一个线程可以访问该锁定的代码部分(例如共享计数器).其他线程必须等到互斥锁解锁等等.

Mutex1.Lock();
 {
     Mutex2.Lock();
     {
          // Code locked by mutex 1 and 2.
     }
     Mutex2.Unlock();

     // Code locked by mutex 1.
 }
 Mutex1.Unlock();
Run Code Online (Sandbox Code Playgroud)

如果我写多个互斥锁会发生什么?
这两个互斥锁是否会被同一个线程选中?我还读到多个互斥锁可能导致死锁.
谁能解释并提供一个例子,说明如何通过用2个互斥锁锁定部分代码来导致死锁?

Ton*_*ous 5

一个线程可以持有多个锁,是的。并且即使只获取了一个互斥锁,也确实可能发生死锁..看工作流程:

线程 A

. 
.
.
lock mutex1
.
<---- Context switch! ----->
Run Code Online (Sandbox Code Playgroud)

线程 B

.
.
.
.
lock mutex2
.
.
.
try lock mutex1 ----> BLOCKED UNTIL THREAD A RELEASES LOCK!
Run Code Online (Sandbox Code Playgroud)

线程 A

.
.
.
try lock mutex2 ---> BLOCKED UNTIL THREAD B RELEASES LOCK!
Run Code Online (Sandbox Code Playgroud)

僵局!

阅读本文,一些互斥类型,例如PTHREAD_MUTEX_NORMAL 可能会导致线程自身死锁。

.
.
.
lock mutex
.
.
.
try lock
Run Code Online (Sandbox Code Playgroud)


How*_*ant 5

这是编写描述内容的安全方法:

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()
Run Code Online (Sandbox Code Playgroud)

该代码无法死锁,因为std::lock(Mutex1, Mutex2)这两个锁都同时锁定,同时避免死锁(通过某些内部算法)。使用的优点std::lock是您不必记住锁定互斥锁的顺序(这使得在大型代码库中维护变得更容易)。但是缺点是您需要在代码中的单个点上锁定两个锁。如果您不能同时锁定它们,那么您就必须按照其他答案的描述退回到顺序。

此代码也是异常安全的,因为如果在任何地方抛出任何异常,则在异常传播时,任何可能被锁定的内容都将被解锁。