为什么这个自旋锁需要 memory_order_acquire_release 而不是仅仅获取?

Huy*_* Le 7 c++ multithreading mutex atomic spinlock

// spinlockAcquireRelease.cpp

#include <atomic>
#include <thread>

class Spinlock{
  std::atomic_flag flag;
public:
  Spinlock(): flag(ATOMIC_FLAG_INIT) {}

  void lock(){
    while(flag.test_and_set(std::memory_order_acquire) ); // line 12
  }

  void unlock(){
    flag.clear(std::memory_order_release);
  }
};

Spinlock spin;

void workOnResource(){
  spin.lock();
  // shared resource
  spin.unlock();
}


int main(){

  std::thread t(workOnResource);
  std::thread t2(workOnResource);

  t.join();
  t2.join();

}
Run Code Online (Sandbox Code Playgroud)

注释中说:

如果两个以上的线程使用自旋锁,则 lock 方法的获取语义是不够的。现在lock方法是一个获取-释放操作。因此第 12 行 [对 的调用] 中的内存模型flag.test_and_set(std::memory_order_acquire)必须更改为std::memory_order_acq_rel

为什么这个自旋锁适用于 2 个线程,但不适用于超过 2 个线程?导致此自旋锁出错的示例代码是什么?

来源: https: //www.modernnescpp.com/index.php/acquire-release-semantic

LWi*_*sey 4

std::memory_order_acq_rel不需要。

互斥同步是在两个线程之间进行的。一个线程释放数据,另一个线程获取数据。
因此,其他线程执行释放或获取操作是无关的。

如果获取由独立的栅栏处理,也许会更直观(也更有效):

void lock(){
  while(flag.test_and_set(std::memory_order_relaxed) )
    ;
  std::atomic_thread_fence(std::memory_order_acquire);
}

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

多个线程可以在 上旋转flag.test_and_set,但一个线程设法读取更新的值并再次设置它(在单个操作中)..只有该线程在 while 循环之后获取受保护的数据。