最小値と最大値を持つアトミック整数変数が 1 つあります。2 つのスレッドが変数を更新し、1 つはそれをインクリメントし、もう 1 つはデクリメントします。インクリメントによって値が最大値を超えて増加する場合、スレッドはブロックされ、条件変数を待ちます。値が最小値に達すると、デクリメントでも同じことが起こります。値が減分され、古い値が最大値である場合、減分スレッドは増分スレッドに通知する必要があり、増分時には同じことが逆に発生するはずです。
デクリメント関数本体:
if (atomic_var.load(std::memory_order_acquire) == minimum) {
std::unique_lock<std::mutex> lk(mutex);
if (atomic_var.load(std::memory_order_acquire) == minimum) {
//we have hit the minimum so we have to wait for the other thread to increase the variable
condition_var.wait(lk, [&]() {
return atomic_var.load(std::memory_order_relaxed) > minimum;
});
}
//do stuff
std::atomic_fetch_sub_explicit(&atomic_var, 1u, std::memory_order_release);
lk.unlock();
condition_var.notify_all();
return;
}
//do stuff
if (std::atomic_fetch_sub_explicit(&atomic_var, 1u, std::memory_order_release) == maximum) {
//we have hit the maximum so the other thread might be waiting
std::atomic_thread_fence(std::memory_order_acquire);
condition_var.notify_all();
}
//adding condition_var.notify_all() here fixes the problem but I'm afraid
//that causes a bit too great performance penalty when it could be easily avoided
これらのチェックにはどのメモリ順序を使用する必要がありますか? 私の現在の実装では、デッドロックが発生しているようです...
編集:すべてのメモリ順序を std::memory_order_seq_cst に変更しても問題は解決しないようです。