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();
}

image

多个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/

posted @ 2023-08-01 13:17  BuzzWeek  阅读(19)  评论(0编辑  收藏  举报