atomic
原子操作:不会被线程调度机制打断的操作,原子操作基于处理器支持
原子操作的实现
原子锁:使用原子操作实现的锁
原子操作可以大幅减少互斥锁的时间开销,但也会带来调试困难。
atomic_flag
std::atomic_flag
是原子布尔类型。不同于所有
std::atomic
的特化,它保证是免锁的
atomic_flag支持test_and_set(),可以用于实现自旋锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #include <iostream> #include <algorithm> #include <string> #include <vector> #include <map> #include <set> #include <atomic> #include <thread>
using namespace std;
atomic_flag lock=ATOMIC_FLAG_INIT; int all =2000000000;
void consumer() { while(lock.test_and_set()); while(all>0) all--; lock.clear(); }
int main() { vector<thread> ths; for(int i=0;i<10;i++) { ths.push_back(thread(consumer)); } for(int i=0;i<10;i++) { ths[i].join(); }
cout<<all<<endl; return 0; }
|
linux下编译增加动态库参数-lpthread
atomic
std::atomic
对部分数据类型进行原子封装,常用int,char,long。c++20之后将支持对非原子类型的封装
std::atomic
既不可复制亦不可移动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <iostream> #include <atomic> #include <vector> #include <thread> #include <sstream>
std::atomic<bool> ready(false); std::atomic_flag winner = ATOMIC_FLAG_INIT;
void count1m(int i) { while (!ready); for (int i=0; i<1000000; i++); if (!winner.test_and_set()) std::cout << "winner: " << i << std::endl; }
int main() { std::vector<std::thread> ths; for (int i=0; i<100; i++) ths.push_back(std::thread(count1m, i)); ready = true; for (int i=0; i<100; i++) ths[i].join(); return 0; }
|
上例最终只有一个线程竞争到ready,线程安全
atomic<int> 可以执行++,--操作
参考资料
预览: