带有静音的多个锁和僵局的可能性

Multiple locks with mutex and the possibility of a deadlock

本文关键字:僵局 可能性      更新时间:2023-10-16

我是线程的新手,试图理解静音。
我将穆特克斯理解为某个对象(键),它仅由一个线程挑选(如果选择的话,那就是另一个线程线程无法选择它,必须等待)访问我们要锁定的代码的某个部分。
因此,当时只有一个线程可以访问代码的锁定部分(例如共享计数器)。其他线程将必须等到Mutex解锁等等。

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的一个优点是,您不必记住要锁定静音的顺序(这使得维护更容易在大型代码库中)。但是缺点是您需要将两个锁锁定在代码中的一个点上。如果您不能同时锁定它们,那么您必须像其他答案所描述的那样回到订购。

此代码也是例外的安全,因为如果抛出任何例外,则锁定的任何例外都被解锁了。

螺纹可以容纳多个锁,是的。即使仅获得了一个静音,也可能发生僵局。查看工作流程:

线程

. 
.
.
lock mutex1
.
<---- Context switch! ----->

线程B

.
.
.
.
lock mutex2
.
.
.
try lock mutex1 ----> BLOCKED UNTIL THREAD A RELEASES LOCK!

线程

.
.
.
try lock mutex2 ---> BLOCKED UNTIL THREAD B RELEASES LOCK!

僵局!

阅读此内容,一些静音类型,例如PTHREAD_MUTEX_NORMAL 可能会导致线程也使其自我僵硬。

.
.
.
lock mutex
.
.
.
try lock

如果我编写多个静音锁会发生什么?都会挑选互音吗 通过同一线程?

螺纹可以同时握住任意数量的静音。在您的示例代码中,进入受Mutex1保护区域的线程将尝试获取Mutex2,等待另一个线程在必要时首先发布它。您提出的代码中没有特殊原因认为它不会成功。

我还读到可能导致多个静音锁 僵局。谁能解释我如何造成僵局 用2个静音锁定代码的一部分?

假设有两个螺纹,一个握住互斥X1,另一个持有sutex2(在这种情况下,至少后者必须运行与伪代码不同的东西)。现在,假设每个线程都尝试获取另一个互斥X,而又不会释放它已经保留的二线。第一个线程必须获取Mutex2进行进行,并且直到另一个释放它才能进行。第二个线程必须获取Mutex1进行进行,并且直到另一个释放它才能进行。ergo, thread can can can em ever 继续 - 这是一个僵局。

一般规则是:如果有一组静音,所有两个或多个线程都可以单独地固定,则必须在获取任何子集时进行每个线程的固定相对顺序其中。