使用atomic_flag自旋锁进行内存排序

iol*_*olo 5 c++ atomic c++11

我试图熟悉c ++ 11的新内存排序概念,并相信我对它们有很好的把握,直到我偶然发现了自旋锁的这种实现:

#include <atomic>

namespace JayZ
{
    namespace Tools
    {
        class SpinLock
        {
        private:
            std::atomic_flag spin_lock;
        public:
            inline SpinLock( void ) : atomic_flag( ATOMIC_FLAG_INIT ) {}

            inline void lock( void )
            {
                while( spin_lock.test_and_set( std::memory_order_acquire ) )
                    ;
            }

            inline void unlock( void )
            {
                lock.clear( std::memory_order_release );
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

例如,在http://en.cppreference.com/w/cpp/atomic/atomic_flag
和"并行行动"一书中提到了相同的内容.我也在SO的某处找到了它.

但我只是不明白它为什么会起作用!
想象一下,线程1调用lock(),test_and_set()返回0作为旧值 - >线程1获得锁定.
但随后线程2出现并尝试相同.现在因为没有发生"存储同步"(release,seq_cst_acq_rel),所以线程1的spin_lock存储应该是轻松的类型.
但是由此得出它不能与线程2的spin_lock读取同步.这应该使线程2能够从spin_lock读取值0,从而获得锁定.
我的错误在哪里?

Dav*_*rtz 5

你的错误是忘记了spin_lock是一个atomic_flag,因而test_and_set是一个原子操作.的memory_order_acquirememory_order_release从所述锁定操作之前迁移到需要的,以防止读出或从解锁后迁移到写入.锁本身受原子性保护,原子性始终包括可见性.

  • 你可以说原子变量实际上做了很多人错误地认为易变量变量的事情. (8认同)
  • 但如果你说的是真的。这不是意味着对原子变量的任何宽松存储都会立即对另一个线程可见吗?事实并非如此,是吗? (2认同)
  • @ bames53:没有"商店发生的任何订单"这样的事情.这些商店是*无序的*.这并不意味着它们必须以两种可能的顺序中的一种发生,这意味着它们不会在订单中发生.(您正在做出无效的假设,即存在一些全局时间概念,并且每个加载或存储都发生在此全局时间轴中的某个定义点.不需要该时间模型.)不同原子变量的操作是无序的,除非您特别强制订购. (2认同)