簡體   English   中英

線程安全隊列死鎖

[英]Thread Safe Queue Deadlocks

我寫了一個線程安全隊列,它給出了死鎖錯誤。 我無法找出原因。 我修改了函數以使用本地鎖,而不是成員變量鎖。 然后,它似乎運行良好。

碼:

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 /鎖定線程使用。 要從另一個線程鎖定,您需要另一個鎖定。 這樣的結果-在每個函數中使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...
}

...

等等。

考慮刪除類內部的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;
}

原因在注釋中得到了很好的解釋:-)。

如果您想提供const成員函數,例如empty() ,則可能還需要將mtx更改為mutable 或復制構造函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM