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个互斥锁锁定部分代码来导致死锁?
一个线程可以持有多个锁,是的。并且即使只获取了一个互斥锁,也确实可能发生死锁..看工作流程:
线程 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)
这是编写描述内容的安全方法:
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是您不必记住锁定互斥锁的顺序(这使得在大型代码库中维护变得更容易)。但是缺点是您需要在代码中的单个点上锁定两个锁。如果您不能同时锁定它们,那么您就必须按照其他答案的描述退回到顺序。
此代码也是异常安全的,因为如果在任何地方抛出任何异常,则在异常传播时,任何可能被锁定的内容都将被解锁。