如何原子地否定 std::atomic_bool
How to atomically negate an std::atomic_bool?
朴素布尔否定
std::atomic_bool b;
b = !b;
似乎不是原子的。我怀疑这是因为operator!
触发了普通bool
的演员表。一个人如何原子地执行等价否定?以下代码说明了朴素否定不是原子的:
#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次。
编辑:对于那些想要运行此代码的人,我在 ubuntu 4.7 上使用具有两个内核的 GCC 11.10 快照。编译选项包括:
-std=c++0x -Wall -pedantic-errors -pthread
b = !b
不是原子的,因为在C++源中,您有一个b
的原子纯读取(相当于b.load()
,然后是b
的单独原子赋值(相当于b.store()
(。
在C++抽象机器中,没有任何内容可以将整个组合转换为原子 RMW 操作,并且没有将任意操作组合为原子 RMW 操作的语法(除了将其放入 CAS 重试循环(。
有两个选项可以使用:
代替
atomic<bool>
,使用整型(例如atomic<int>
或atomic<unsigned char>
(,可以是 0 或 1,也可以是 1 或 xor :std::atomic<int> flag(0); flag ^= 1; //equivalent to flag.fetch_xor(1);
不幸的是,
fetch_xor
没有在atomic<bool>
上提供,只在整型上提供。在循环中执行比较/交换操作,直到成功:
std::atomic<bool> flag(false); bool oldValue = flag.load(); while (!flag.compare_exchange_weak(oldValue, !oldValue)) {}
不幸的是,x86 的编译器通常不会将此循环优化为
lock xor byte [flag], 1
在 ASM 中;您将获得一个实际的 CMPXCHG 重试循环。 实际上,cmpxchg 重试循环在低争用的情况下很好。 在最坏的情况下,这不是无等待的,而是无锁的,因为每次重试时,至少有一个线程都会取得进展。 (实际上,硬件仲裁更为复杂,内核甚至可以访问缓存行进行尝试。如果可能存在高争用,则首选允许您使用原子异或的整数版本。
- 写入向量<向量<bool>>
- 如何从 std::atomic 中提取指针 T<T>?
- std::atomic和std::condition_variable wait,notify_*方法之间的区别
- std::memory_order for std::atomic:<T>:wait
- MESI协议和std::atomic-它是否确保所有写入立即对其他线程可见?
- 让bool方法返回其他整数
- 如何在 std::vector 中找到<bool>哪些索引是真的?
- Arduino-C++ bool 不会从 false 变为 true
- 为什么在这种情况下,bool 类型的输出等于 0?
- 显式 std::exception_ptr 转换为 bool 不存在.VS2010 错误?
- 错误:不能使用"显式"说明符声明 bool'
- 为什么 C++ 11 在 ios 类中添加了运算符 bool
- 将 std::atomic<bool> 与 std::mutex 结合使用的正确性
- 在 c++ 中使用 std::atomic 的比较和读/写操作<bool>?
- 引用 std::atomic <bool>的已删除函数错误
- std::<bool>atomic和lambda
- 为什么 std::atomic<bool> 比挥发性布尔值慢得多?
- 赋值是否等同于 std::atomic <bool>的加载/存储
- 使用 std::atomic::atomic 时出现错误 C2248<bool>
- C++ std::atomic:<bool>:fetch_or 未实现?