C++ 多线程 atomic

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/z8110/article/details/84672237

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的,但是在中间执行过程中并不是一直相等的。

猜你喜欢

转载自blog.csdn.net/z8110/article/details/84672237
今日推荐