C++ 多线程 atomic
atomic 先上翻译。
aotomic原子的 即不能分割的,最小单位。
举个例子,int num;
num = num +1;
我们都知道对于num=num+1这条程序语句需要分解为三步,
1、把变量num读取到某一个寄存器R存储,
2、CPU对寄存器R的值进行计算,
3、计算完成后将值存回内存
在多线程执行num++的时候 当前num为1 线程A执行完第二步 此时num为2但是还没有存入内存,然后线程B开始执行第一步,从内存中取出num,num依旧是1,这样就出现问题了,相当于A线程和B线程一共执行了连词num=num+1,但是num却只增加了1,。
我们测试一下:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<thread>
#include<map>
#include<stack>
#include<vector>
#include<atomic>
#include<Windows.h>
#include<algorithm>
using namespace std;
class Unit
{
public :
Unit() { this->num = 0; this->step = 0; this->numnum = 0; this->stepnum = 0; };
void ChangeStepNum()
{
step = step + 1;
num = num + 1;
//++step;
//++num;
}
void ChangeStep()
{
step++;
}
void ChangeNum()
{
num++;
}
void GetAve()
{
if (this->num == this->step)
cout << "Good" << endl;
else
cout << "Bad" << endl;
}
void PrintStepNum()
{
cout << "num" << this->num << endl;
cout <<"step" << this->step << endl;
}
void equal()
{
if (this->num != this->step)
cout << "???" << endl;
}
private :
//atomic <int> step;
//atomic <int> num;
int step;//定义变量
int num;//让这两个变量同时改变
int stepnum;
int numnum;
};
void Change(Unit &unit)//同时改变两个变量
{
for (int i = 0; i < 10000; i++)
{
//unit.equal();
unit.ChangeNum();
unit.ChangeStep();
}
unit.GetAve();
}
int main()
{
Unit unit;
thread t1(Change, ref(unit));//线程1
thread t2(Change, ref(unit));//线程2
t1.join();
t2.join();
unit.PrintStepNum();
Sleep(1000);
for (int i = 0; i < 10000; i++)
{
unit.ChangeNum();
unit.ChangeStep();
}
unit.PrintStepNum();
}
测试结果
我们可以看到,由于上边阐述的原因 ,导致num和step一共改变了20000次但是最后结果却不是20000,而且num!=step.
如果我们改成原子操作atomic,即atomic修饰的操作不可分割,未 修饰是num=num+1执行了三步:修饰之后变成了一步,变成了一个原子,不可分割。
atomic <int> step;
atomic <int> num;
//int step;//定义变量
//int num;//让这两个变量同时改变
测试结果
如果num== step就输出good 否则输出bad。
我们可以看到num是== step 的 而且 经过20000次++之后 ,确实加到了20000。
不过 还有一个问题,就是num和step是一起操作的,但是num和step一直都相等吗。
应该不是的,对于AB两个线程
void Change(Unit &unit)//同时改变两个变量
{
for (int i = 0; i < 10000; i++)
{
//unit.equal();
unit.ChangeNum();
unit.ChangeStep();
}
unit.GetAve();
}
可能A线程刚执行到changenum时,B线程已经执行到changestep了,虽然我们给这两个变量加了atomic。
此时我们在change之前加一个判断函数,如果num!=step则问号警告。
测试一下:
可以得出,虽然最后num是==step的,但是在中间执行过程中并不是一直相等的。