C++ 对于关键部分-何时使用std::mutex vs std::atomic_标志?

C++ 对于关键部分-何时使用std::mutex vs std::atomic_标志?,c++,stl,C++,Stl,下面是一个使用STL原子_标志的Spinlock类的实现,取自 我可以将其用于代码的任何关键部分: void myfunction() { std::lock_guard<Spinlock> guard(_spinLock); ... } void myfunction(){ 标准:锁紧/防护装置(旋转锁); ... } 修订问题: 对于关键部分,我现在似乎有两个选择——std::mutex和std::atomic_标志。什么时候使用一个比另一个更有意义?

下面是一个使用STL原子_标志的Spinlock类的实现,取自

我可以将其用于代码的任何关键部分:

 void myfunction() {
     std::lock_guard<Spinlock> guard(_spinLock);
     ...
 }
void myfunction(){
标准:锁紧/防护装置(旋转锁);
...
}
修订问题:


对于关键部分,我现在似乎有两个选择——std::mutex和std::atomic_标志。什么时候使用一个比另一个更有意义?

std::mutex
也可以与一起使用,而您的类不能直接使用。它还可以很好地处理作用域锁

你的声明不必说了

效率更高

这并非绝对正确。线路

while( flag.test_and_set() );

例如,在某些情况下是有效的,而在其他情况下则不如指数退避。

问题是:你想要实现什么,你愿意为此做出什么牺牲

std::atomic_flag不断请求锁访问关键部分,从而使运行它的CPU核心保持100%忙碌。如果您有足够的内核可以使用,或者没有多少线程同时在同一个关键部分上运行,那么这就不会是一个问题。它节省了用户空间和内核空间之间昂贵的上下文切换


另一方面,std::mutex将不会使其核心保持忙碌状态。使用此解决方案,您无法在任何内核上观察到明显的负载。这是因为当其他线程执行某些工作时,该线程被调度程序挂起。这意味着线程的状态将被存储,然后恢复并在以后恢复。

“而且它更高效”[需要引用]。这是一个相当宽泛的说法。在任何情况下,自旋锁都不是互斥锁的最佳实现。这里有一条引文:。那篇文章中的自旋锁与互斥锁部分是一个非常好的演示,说明自旋锁并不总是有效的。在spinlock示例中,所使用的程序什么都不做(实际上只是休眠),但却占用了一个完整的CPU内核。通常应避免使用spinlock。在最好的情况下,它们在延迟方面给了您一个微小的改进,在最坏的情况下,它们可能会导致优先级反转,这是由于抛开了调度程序的启发。几个月前,Linus Torvalds不得不就Stadia的一位开发者对各种锁定机制的糟糕基准测试以及他们的结论如何是“纯粹的垃圾”(原文如此)一事进行反驳。我对效率的评论是基于我现在添加到原始帖子中的引用。谢谢。@Peter我不确定你怎么看它更高效。它指出的是,自旋锁表现出您期望的行为(捆绑核心),而互斥锁则不这样做。捆绑核心本身并不是效率的标志。完成更多的工作量是非常重要的。
while( flag.test_and_set() );