c++ - 使用 "got there first"标志而不是锁/互斥来同步对数据的访问

标签 c++ multithreading c++11 atomic

假设我们有一个访问一些全局共享数据的函数 - 并且假设这个函数将被多个并发线程调用。

自然地,我们需要以某种方式同步对这些数据的访问。是否有可能通过我们有一个原子标志的机制来做到这一点,然后无论哪个线程设法设置标志都可以继续访问共享数据?而丢失的线程不会阻塞在锁上,而只是从函数中返回。

类似下面的内容:

给定一些全局共享的数据以及一个同步标志:

namespace global {

  int x;
  int y;

  std::atomic_flag sync_flag = ATOMIC_FLAG_INIT;

}

我们的函数将被并发线程访问:

void race()
{
   // See if we won the race
   //
   if (!global::sync_flag.test_and_set())
   {
      // We won
      //
      global::x = 10;
      global::y = 11;
   }
   else
   {
     // We lost... 
     return;
   }
}

上述代码是否保证global::xglobal::y 将仅由单个线程安全访问,并且不会出现竞争条件?还是由于内存排序问题,这不能得到保证?

请注意,我们实际上从未锁定互斥量或任何东西,因此没有线程最终阻塞。这里的想法只是为了确保只有一个线程被允许在这里访问(非原子)全局变量。

当然,在获胜线程完成后,如果我们打算再次调用 race(),我们需要以某种方式安全地清除原子标志。这是一个我还没有想太多的问题,但它确实超出了这个问题的范围。

那么上面的代码是否没有竞争条件(对于 race() 的单个调用)?

最佳答案

是的。只有一个线程可以在标志上获得尚未设置的测试。这比互斥锁有一个优势,因为在某些体系结构上,原子标志可以通过无锁操作完成。

关于c++ - 使用 "got there first"标志而不是锁/互斥来同步对数据的访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30948958/

相关文章:

c++ - opencv cv::Ptr 的动态转换

c++ - pthreads - 先前创建的线程使用新值(线程创建后更新)

c++ - 在现代 OpenGL 和 C++ 中渲染 Quake BSP

Java:扩展 Thread 而不实现 run()

c++ - 使用 g++ 删除了 linux 中的 std basic_stringstream 函数

c++ - 如何比较容器和初始化列表以查看它们是否相等?

c++ - Eric Niebler 的 std::is_function 实现如何工作?

c - 释放线程内存

c++ - 利用 C++11 中 int*_t、int_fast*_t 和 int_least*_t 之间的差异的一个好例子是什么?

c++ - 在 C++ 中调用带括号的枚举/枚举类时发生了什么?