《C++11 基于CAS无锁操作的atomic原子类型》
count++;
count--;
我们知道,++/--操作并不是原子性的,其实对应三条汇编指令来完成的。
- 读取:从内存中把变量的值读取到寄存器
- 修改:在寄存器里将变量的值+1/-1
- 写入:把修改后的值写入到内存
在单线程环境下,这三个步骤是顺序执行的不会有问题。但是在多线程环境下,多个线程可能对同一个变量同时进行++/--操作,从而导致数据竞争的问题。
可以看下面的过程演示。
一:
二:
三:
C++11是通过加锁来保证++/--操作的原子性的。
std::lock_guard<std::mutext>(mtx);
count++;
std::unlock_guard<std::mutex>(mtx);
互斥锁是比较重的,临界区代码稍稍复杂的情况下建议使用。从系统理论上来讲,使用CAS无锁操作来保证++/--操作的原子性就足够了,其实并不是不加锁,只是不在软件层面上加锁解锁,而是在硬件层面上实现的。
#include<iostream>
#include<thread>
#include<list>
#include<atomic>
using namespace std;
volatile std::atomic_bool isReady = false;
volatile std::atomic_int myCount = 0;
void task()
{
while (!isReady)
{
std::this_thread::yield(); // 线程让出当前的CPU时间片,等待下一次调度
}
for (int i = 0; i < 100; i++)
{
myCount++;
}
}
int main()
{
list<std::thread> tlist;
for (int i = 0; i < 10; i++)
{
tlist.push_back(std::thread(task));
}
std::this_thread::sleep_for(std::chrono::seconds(3));
isReady = true;
for (auto& t : tlist)
{
t.join();
}
std::cout << "myCount: " << myCount << std::endl;
return 0;
}