c++11atomic原子锁

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;

//静态化初始化,c++11起,c++20弃用,定义即初始化
atomic_flag lock=ATOMIC_FLAG_INIT;
int all =2000000000;

//消费者进程
void consumer()
{
//测试锁状态,为false置true,退出循环(自旋)
while(lock.test_and_set());
while(all>0) all--;
//解锁,lock置false
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> 可以执行++,--操作

参考资料