c++多线程同步问题
一个mutex导致的死锁问题
单核实时可抢占的系统中,优先级不同的三个线程A/B/C, A>B>C
- 当C先获得时间片开始执行,并获得锁
- A因为高优先级,被唤醒并中断C,但没有得到锁,而阻塞
- B获得执行机会,由于优先级高于C,B会一直执行,让AC系统无法取得任何进展
std::stack<T> stack;
std::mutex mutex;
void push(const T& obj) {
mutex.lock();
stack.push(obj);
mutex.unlock();
}
多个mutex导致的死锁问题
- 多个锁共同控制临界区
- 加锁顺序不一致
- A,B锁被两个线程分别持有,等待对方释放剩下的锁,不会主动释放所持有的锁,而导致死锁
#include <mutex>
#include <iostream>
#include <thread>
using namespace std;
mutex lockA;
mutex lockB;
int counter{0};
void foo() {
while(true) {
lock_guard<mutex> guardA(lockA);
lock_guard<mutex> guardB(lockB);
cout << "message from foo " << counter++ << endl;
}
}
void bar() {
while(true) {
lock_guard<mutex> guardB(lockB); // 注意这里加锁顺序
lock_guard<mutex> guardA(lockA);
cout << "message from bar " << counter++ << endl;
}
}
void DeadLockTest() {
thread tf(foo);
thread tb(bar);
tf.join();
tb.join();
}
解决多个锁导致死锁问题
- 尽量只用一个锁
- 如果必须用多个锁,注意顺序上锁
- 无法保证上锁顺序的话,使用std::lock
void foo() {
while(true) {
std::lock(lockA, lockB);
lock_guard<mutex> guardA(lockA, std::adopt_lock);
lock_guard<mutex> guardB(lockB, std::adopt_lock);
cout << "message from foo " << counter++ << endl;
}
}
void bar() {
while(true) {
std::lock(lockB, lockA);
lock_guard<mutex> guardB(lockB, std::adopt_lock); // 注意这里加锁顺序
lock_guard<mutex> guardA(lockA, std::adopt_lock);
cout << "message from bar " << counter++ << endl;
}
}
- 或者使用try_lock
void foo() {
while(true) {
if (std::try_lock(lockA, lockB) == -1) {
cout << "message from foo " << counter++ << endl;
lockA.unlock();
lockB.unlock();
}
}
}
void bar() {
while(true) {
if (std::try_lock(lockB, lockA) == -1) {
cout << "message from bar " << counter++ << endl;
lockB.unlock();
lockA.unlock();
}
}
}
参考
https://en.cppreference.com/w/cpp/thread/lock
http://en.cppreference.com/w/cpp/thread/lock_guard
https://cplusplus.com/reference/mutex/try_lock/