デッドロックエラーを発生させるスレッドセーフキューを作成しました。私は理由を理解することができません。私は、メンバー変数ロックの代わりにローカルロックを使用するように関数を変更しました。それから、うまく走っているようです。スレッドセーフキューのデッドロック
コード:
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;
}
};
エラー:私のコメントを1として
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()メソッドでキューをロックし、空であれば要素があるまで待機します。追加します。ロック障壁の間に決して待ってはいけません。また、使用されているスコープにロックを作成して、スコープが例外の場合でもクリーンアップするようにするか、例外的にロックが解放されることもあります。 – Rob
@Rob - 条件変数は、原子的に待機を開始し、/を保護するmutexをロック解除します。その部分はOKで、標準的な使い方です。 – BadZen