在阅读了问题 C++20 mutex withatomic wait 以及 有时可以使用 std::atomic 而不是 C++ 中的 std::mutex 吗?虽然类似,但我的疑问不同,我有这个疑问下面会解释一下:
我想知道调用 std::atomic::wait 函数来同步一段代码是否安全,正如许多人所建议的那样,似乎可以使用 std::atomic::wait,但我相信这也许并不完全安全,有发生死锁的风险
想象下面的代码:
#include <atomic>
#include <iostream>
#include <thread>
#include <vector>
std::atomic<bool> lock = false;
void go(){
bool expected = false;
while(!lock.compare_exchange_strong(expected, true)) {
lock.wait(true);
expected = false;
}
std::cout << "Sincronizado" << std::endl;
lock = false;
lock.notify_all();
}
int main() {
std::vector<std::thread> threads;
threads.reserve(2);
for(int i = 0; i < 2; i++)
threads.emplace_back(go);
for(auto& thread : threads)
thread.join();
}
到目前为止一切顺利,您可能已经在几个 Stackoverflow 问题中看到过它,但现在考虑以下场景:
while(!lock.compare_exchange_strong(expected, true))
lock = false;
while(!lock.compare_exchange_strong(expected, true))
lock.wait(true);
if
锁定是否为真 FUTEX_WAIT
) 线程被抢占 lock.notify_all();
这种情况可能发生还是我偏执了?
对于任何混乱,我深表歉意,我正在使用谷歌翻译,如果您有任何疑问,请使用评论。
卢卡斯·P.
你的
compare_exchange_strong
循环是不必要的,std::atomic::wait
已经为你做到了这一点:
执行原子等待操作。其行为就像重复执行以下步骤:
- 将
的值表示与this->load(order)
的值表示进行比较。old
- 如果它们相等,则阻塞,直到
或*this
通知notify_one()
,或者线程被虚假地解除阻塞。notify_all()
- 否则返回。
这些函数只有在值发生变化时才保证返回,即使底层实现虚假地解除阻塞。
wait
是原子的,所以最坏的情况下它会在你调用notify
之前解锁,你永远不会像使用条件变量那样错过通知。