问题描述
天真的布尔否定
std :: atomic_bool b;
b =!b;
似乎不是原子。我怀疑这是因为运算符!
触发一个转换为简单 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;
}
}
//启动nThreads std :: threads。每个线程调用flipAHundredThousandTimes
//在同一个布尔
void launchThreads(Bool& foo,size_t nThreads){
std :: vector< std :: thread>线程;
for(size_t i = 0; i threads.emplace_back(flipAHundredThousandTimes,std :: ref(foo));
}
for(auto& thread:threads)thread.join();
}
int main(){
std :: cout< std :: boolalpha;
Bool foo {true};
//启动并加入10个线程,20次。
for(int i = 0; i launchThreads(foo,10);
std :: cout<< Result(should be true):<< foo< \\\
;
}
}
代码启动10个线程其中翻转atomic_bool一个larrge,甚至,次数(100000),并打印出布尔值。这重复20次。
编辑:对于那些想要运行这个代码,我使用一个GCC 4.7快照ubuntu 11.10与两个内核。编译选项为:
-std = c ++ 0x -Wall -pedantic-errors -pthread
b =!b
有两个选项可供使用:
-
而不是
atomic
,使用整数类型(例如<$ c $可以是0或1,并且与1:std :: atomic< int>标志(0);
flag ^ = 1; //或flag.fetch_xor(1);不幸的是,fetch_xor
不提供 -
在循环中执行一个比较/交换操作,直到成功:
std :: atomic< bool> flag(false);
bool oldValue = flag.load();
while(!flag.compare_exchange_weak(oldValue,!oldValue)){}
The naive boolean negation
std::atomic_bool b;
b = !b;
does not seem to be atomic. I suspect this is because operator!
triggers a cast to plain bool
. How would one atomically perform the equivalent negation? The following code illustrates that the naive negation isn't atomic:
#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";
}
}
The code launches 10 threads, each of which flips the atomic_bool a larrge, even, number of times (100000), and prints out the boolean. This is repeated 20 times.
EDIT: For those who want to run this code, I am using a GCC 4.7 snapshot on ubuntu 11.10 with two cores. The compilation options are:
-std=c++0x -Wall -pedantic-errors -pthread
b = !b
is not atomic because it is comprised of both a read and a write, each of which is an atomic operation.
There are two options to use:
Instead of
atomic<bool>
, use an integral type (e.g.atomic<int>
) which can be 0 or 1, and xor it with 1:std::atomic<int> flag(0); flag ^= 1; //or flag.fetch_xor(1);
Unfortunately,
fetch_xor
is not provided onatomic<bool>
, only on integral types.Perform a compare/exchange operation in a loop, until it succeeds:
std::atomic<bool> flag(false); bool oldValue = flag.load(); while (!flag.compare_exchange_weak(oldValue, !oldValue)) {}
这篇关于如何原子地否定std :: atomic_bool?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!