我寫了一個線程安全隊列,它給出了死鎖錯誤。我無法找出原因。我修改了函數來使用本地鎖,而不是成員變量鎖。然後,它似乎運行良好。線程安全隊列死鎖
代碼:
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