我写了一个线程安全队列,它给出了死锁错误。我无法找出原因。我修改了函数来使用本地锁,而不是成员变量锁。然后,它似乎运行良好。线程安全队列死锁
代码:
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
正如其名称所暗示的那样,'unique_lock'仅供/ one/locking线程使用。要从另一个线程锁定,您需要另一个锁。结果是 - 在每个函数中使'unique_lock'成为本地,而不是类成员。 – BadZen
我看到一个大问题:你在你的pop()方法中锁定你的队列,如果它是空的,你等待/循环,直到它有一个元素。这不会发生,因为你有它锁定,所以push()不能锁定它加。永远不要在锁屏之间等待。你也应该在它使用的范围内创建锁,这样当范围存在时,即使在例外的情况下,它也会被清除,或者你最终可能得到一个在异常情况下也不会被释放的锁。 – Rob
@Rob - 条件变量自动等待开始等待和/解锁保护条件的互斥/。这部分是好的,并且是标准用法。 – BadZen