线程安全队列死锁

时间:2016-11-15 14:27:20

标签: c++ multithreading c++11 thread-safety locking

我编写了一个线程安全队列,它会出现死锁错误。我无法弄清楚原因。我修改了函数以使用本地锁,而不是成员变量锁。然后,它似乎运行良好。

代码:

template <typename T>
class MyQueue {
queue<T> arr;

mutex mtx;
unique_lock<mutex> lck;
condition_variable cv;
public:
MyQueue() {
    lck = unique_lock<mutex>(mtx, defer_lock);
}

void push(int tmp) {
    lck.lock();
    arr.push(tmp);
    lck.unlock();
    cv.notify_one();
}

int pop() {
    T x;
    lck.lock();
    while(arr.size() == 0)
        cv.wait(lck);
    x = arr.front();
    arr.pop();
    lck.unlock();
    return x;
}

int getCount() {
    T x;
    lck.lock();
    x = arr.size();
    lck.unlock();

    return x;
}
};

错误:

libc++abi.dylib: libc++abi.dylib: libc++abi.dylib: terminating with
uncaught exception of type std::__1::system_error: unique_lock::lock: already locked:
Resource deadlock avoidedterminating with uncaught exception of type std::__1::system_error: 
unique_lock::lock: already locked: Resource deadlock avoidedlibc++abi.dylib: 
terminating with uncaught exception of type std::__1::system_error: unique_lock::lock: already locked: Resource deadlock avoided

2 个答案:

答案 0 :(得分:1)

根据我的评论:顾名思义,unique_lock仅供/ one / lock线程使用。要从另一个线程锁定,您需要另一个锁。这样做的结果 - 使unique_lock在每个函数中都是局部的,而不是类成员。

template <typename T>
class MyQueue {
queue<T> arr;

mutex mtx;
condition_variable cv;
public:
MyQueue() {
}

void push(int tmp) {
    unique_lock<mutex> lck(mtx);
    arr.push(tmp);
    cv.notify_one();
    lck.unlock(); // Not nec'y, but polite...
}

...

等等。

答案 1 :(得分:0)

考虑删除内部unique_lock内容,并将pushpop功能更改为以下内容:

void push(int tmp)
{
    std::lock_guard<std::mutex> lkg(mtx); // Here unique_lock not necessary.
    arr.push(tmp);
    cv.notify_one();
}

int pop()
{
    std::unique_lock<std::mutex> ulk(mtx);
    cv.wait(ulk, [this]() { return arr.size() != 0; });

    auto x = arr.front();
    arr.pop();
    return x;
}

原因在评论中得到了很好的解释: - )。

如果您想提供mtx成员函数,您可能还想将mutable更改为const;或复制构造函数。