[英]Thread Safe Queue Deadlocks
I have written a thread safe queue which gives deadlock error. 我写了一个线程安全队列,它给出了死锁错误。 I am unable to figure out reason. 我无法找出原因。 I modified the functions to use local locks, instead of member-variable lock. 我修改了函数以使用本地锁,而不是成员变量锁。 Then, it seems to run fine. 然后,它似乎运行良好。
Code: 码:
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;
}
};
Error: 错误:
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
As per my comment: unique_lock, as the name implies, is intended for use by only /one/ locking thread. 根据我的评论:顾名思义,unique_lock仅供/ one /锁定线程使用。 To lock from another thread, you need another lock. 要从另一个线程锁定,您需要另一个锁定。 The upshot of this - make unique_lock a local in each function, and not a class member. 这样的结果-在每个函数中使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...
}
...
and so forth. 等等。
Consider deleting the unique_lock
inside class, and changing your push
and pop
function to the following: 考虑删除类内部的unique_lock
,并将push
和pop
函数更改为以下内容:
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;
}
The reasons are very well explained in the comments :-). 原因在注释中得到了很好的解释:-)。
You might also want to change your mtx
to mutable
if you want to provide const
member functions like empty()
; 如果您想提供const
成员函数,例如empty()
,则可能还需要将mtx
更改为mutable
; or copy constructor. 或复制构造函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.