首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何原子地否定std::atomic_bool?

问如何原子地否定std::atomic_bool?
EN

Stack Overflow用户
提问于 2012-03-21 14:04:26
回答 1查看 11.8K关注 0票数 44

朴素布尔否定

代码语言:javascript
复制
std::atomic_bool b;
b = !b;

似乎不是原子的。我怀疑这是因为operator!触发了对普通bool的转换。一个人将如何原子地执行等价的否定?下面的代码说明天真的否定不是原子的:

代码语言:javascript
复制
#include <thread>
#include <vector>
#include <atomic>
#include <iostream>

typedef std::atomic_bool Bool;

void flipAHundredThousandTimes(Bool& foo) {
  for (size_t i = 0; i < 100000; ++i) {
    foo = !foo;
  }
}

// Launch nThreads std::threads. Each thread calls flipAHundredThousandTimes 
// on the same boolean
void launchThreads(Bool& foo, size_t nThreads) {

  std::vector<std::thread> threads;
  for (size_t i = 0; i < nThreads; ++i) {
    threads.emplace_back(flipAHundredThousandTimes, std::ref(foo));
  }

  for (auto& thread : threads) thread.join();

}

int main() {

  std::cout << std::boolalpha;
  Bool foo{true};

  // launch and join 10 threads, 20 times.
  for (int i = 0; i < 20; ++i) {
    launchThreads(foo, 10);
    std::cout << "Result (should be true): " << foo << "\n";
  }

}

代码会启动10个线程,每个线程都会将atomic_bool翻转成大量的偶数(100000次),并打印出布尔值。这种情况重复了20次。

编辑:对于那些想要运行这段代码的人,我使用的是具有两个内核的ubuntu11.10上的GCC 4.7快照。汇编的备选方案如下:

代码语言:javascript
复制
-std=c++0x -Wall -pedantic-errors -pthread
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-03-21 14:27:30

b = !b不是原子的,因为在C++源中有一个b的原子纯读(等价于b.load(),然后是一个单独的原子赋值给b (等效于b.store())。

在C++抽象机器中,没有任何东西使整个组合成为原子RMW操作,也没有将任意操作组合到原子RMW操作中的语法(除了将其放入CAS重试循环中)。

有两个选项可供使用:

  1. 而不是atomic<bool>,使用一个可以是0或1的整数类型(例如atomic<int>或atomic<unsigned char>),然后用1表示它:

:原子标志(0);标志^= 1;//相当于flag.fetch_xor(1);

不幸的是,只有在循环中的整数types.

  • Perform中提供比较/交换操作时,才在atomic<bool>上提供fetch_xor,直到它成功为止:

std::原子标志(False);bool oldValue = flag.load();while (!flag.compare_exchange_weak(oldValue,!oldValue)) {}

不幸的是,x86编译器通常不会将这个循环优化为

asm中的lock xor byte [flag], 1;您将得到一个实际的cmpxchg重试循环。在实践中,cmpxchg重试循环很好,争用较低。在最坏的情况下,这不是没有等待,但是无锁的,因为至少有一个线程将取得进展,每次他们都重试。(实际上,硬件仲裁要复杂得多,核心甚至可以访问缓存行进行尝试。)

如果可能存在较高的争用性,请使用允许使用原子xor.的整数版本。

票数 36
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9806200

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档