C++ std::atomic和std::condition_变量wait,notify_*方法之间的差异
我在浏览“原子操作库”时发现了一个新的c++20特性,即原子的“等待”和“通知”方法。我很好奇std::condition_变量的“wait”和“notify_”方法有什么区别。std:atomicC++ std::atomic和std::condition_变量wait,notify_*方法之间的差异,c++,c++20,condition-variable,stdatomic,C++,C++20,Condition Variable,Stdatomic,我在浏览“原子操作库”时发现了一个新的c++20特性,即原子的“等待”和“通知”方法。我很好奇std::condition_变量的“wait”和“notify_”方法有什么区别。std:atomicwait,notify_all和notify_one方法与条件变量的方法类似。通过使用效率更高、更轻量级的原子变量,它们允许实现以前需要条件变量的逻辑 wait函数阻塞线程,直到修改原子对象的值。它需要一个参数来与原子对象的值进行比较。它反复执行: 如果值相等,它会阻塞线程,直到notify_one
wait
,notify_all
和notify_one
方法与条件变量的方法类似。通过使用效率更高、更轻量级的原子变量,它们允许实现以前需要条件变量的逻辑
wait
函数阻塞线程,直到修改原子对象的值。它需要一个参数来与原子对象的值进行比较。它反复执行:
- 如果值相等,它会阻塞线程,直到
或notify_one
通知线程,或者线程被错误地解除阻塞notify_all
- 否则,将返回
wait
仅在值已更改时保证返回,即使底层实现错误地解除阻塞也是如此
您可以在此处找到实现: 该战略是按平台选择的:
- Linux:默认为futex(带表),回退至futex(无表)->CVs->定时回退->旋转
- Mac:默认为CVs(表),回退到定时回退->旋转
- Windows:默认为futex(无表),回退至定时回退->旋转
- CUDA:默认为定时回退,回退为旋转。(此树中未全部签入。)
- 不明平台:默认为旋转
- 整个使用模式有所不同
条件变量
等待需要互斥锁。在通知之前,应使用相同的互斥锁:
std::mutex mtx;
std::condition_variable cv;
bool condition();
void change_condition();
...
std::unique_lock<std::mutex> lock(mtx);
while (!condition())
{
cv.wait(lock);
}
...
std::unique_lock<std::mutex> lock(mtx);
change_condition();
lock.unlock();
cv.notify_one();
差异是由实现定义的。除了界面之外,可能根本没有区别。我假设原子版本将通过一个更轻量级的方案或其他什么来实现,或者相反,它可能会执行更多的旋转,或者在开始时执行任何操作。虽然它是提案的实现,但作为C++2a特性,它是在STL实现中实现的。真正的实现可能更复杂(在Windows上设置CV后备功能也很有用),也可能更少(此实现在通知futex之前进行检查,但不是强制性的)。
std::mutex mtx;
std::condition_variable cv;
std::atomic<bool> condition;
...
std::unique_lock<std::mutex> lock(mtx);
while (!condition.load())
{
cv.wait(lock);
}
...
std::unique_lock<std::mutex> lock(mtx);
condition.store(true);
lock.unlock();
cv.notify_one();
condition.store(true);
std::unique_lock<std::mutex> lock(mtx);
lock.unlock();
cv.notify_one();
std::atomic<bool> condition;
...
condition.wait(false);
...
condition.store(true);
condition.notify_one();