int a=1 是原子操作吗?

【原子操作定义】

所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。也可以这样理解:如果这个操作所处的层(layer)的更高层不能发现其内部实现与结构,那么这个操作是一个原子(atomic)操作。原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割而只执行其中的一部分。将整个操作视作一个整体是原子性的核心特征。

 

示例一:

给整型变量赋值一个确定的值,如:

int a = 1;

这种指令操作一般是原子的。因为对应着一条计算机指令,cpu将立即数1搬运到变量a的内存地址中即可: 

int _tmain(int argc, _TCHAR* argv[])
{
	//example 1:
	int a = 1;
	//a=1 汇编指令
	_asm
	{
		mov dword ptr[a], 1
	}
	printf("%d\n", a);

	return 0;
}

然而这却是最不常见的情形,由于现代编译器一般有优化策略,如果变量a的值在编译期间就可以计算出来(例如这里的例子中a的值就是1),那么a这个变量本身在正式版本(release版)的软件中就很有可能被编译器优化掉,使用a的地方,直接使用常量1来代替。所以实际的执行指令中,这样的指令存在的可能性比较低。

 

示例二:

变量自身增加或者减去一个值,如:

a++;

从C/C++语法的级别来看,这是一条语句,是原子的。但是从实际执行的二进制指令来看,也不是原子的,其一般对应三条指令,首先将变量a对应的内存值搬运到某个寄存器(如eax)中,然后将该寄存器中的值自增1,再将该寄存器中的值搬运回a的内存中:

int _tmain(int argc, _TCHAR* argv[])
{
	//example 2:
	int a = 0;
	//a++ 汇编指令
	_asm
	{
		mov eax, dword ptr[a]	//step 1
		inc eax			//step 2
		mov dword ptr[a], eax	//step 3
	}
	printf("%d\n", a);

	return 0;
}

现在假设a的值是0,有两个线程,每个线程对变量a的值递增1,我们预想的结果应该是2,可实际运行的结果可能是1!分析如下:

//线程1
void thread_func1(){
	a++;
}

//线程2
void thread_func2(){
	a++;
}

我们预想的结果是线程1和线程2的三条指令各自执行,最终a的值为2。但是由于操作系统线程调度的不确定性,线程1执行完指令step1、2后,eax寄存器中的值为1。此时操作系统切换到线程2执行,执行指令step1、2、3,此时eax的值变为1;接着操作系统切回线程1继续执行,执行指令step3,得到a的最终结果1。

 

其他示例:

把一个变量的值赋值给另外一个变量,或者把一个表达式的值赋值给另外一个变量,如

int a = b;

从C/C++语法的级别来看,这是也是一条语句,是原子的;但是从实际执行的二进制指令来看,由于现代计算机CPU架构体系的限制,数据不可以直接从内存搬运到另外一块内存,必须借助寄存器中断,这条语句一般对应两条计算机指令,即将变量b的值搬运到某个寄存器(如eax)中,再从该寄存器搬运到变量a的内存地址:

mov eax, dword ptr [b]  
mov dword ptr [a], eax 

既然是两条指令,那么多个线程在执行这两条指令时,某个线程可能会在第一条指令执行完毕后被剥夺CPU时间片,切换到另外一个线程而产生不确定的情况。

所以,综上所述,我们在多线程环境中,对变量进行赋值时,也是需要对“资源”进行保护的!

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hellokandy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值