题目:
int global = 0; // thread 1 for(int i = 0; i < 10; ++i) global -= 1; // thread 2 for(int i = 0; i < 10; ++i) global += 1;
之后global的可能的值是多少(多种可能)?
这个问题考虑的是全局变量global的加减操作不是原子操作,在加减过程中有可能被打断,从而产生的结果与预期不一样。上述global加减操作的汇编如下
;windows下加操作 mov eax,dword ptr [globle (10A9148h)] add eax,1 mov dword ptr [globle (10A9148h)],eax ;windows下减操作 mov eax,dword ptr [globle (10A9148h)] sub eax,1 mov dword ptr [globle (10A9148h)],eax ;linux下加操作 movl global, %eax addl $1, %eax movl %eax, global ;linux下减操作 movl global, %eax subl $1, %eax movl %eax, global
可见,不论加减都要经过global的值加载到eax,然后eax加减1,最后再写回global中。这时如果线程1的global的值刚加载到eax中,线程2获取到了执行权,就会出现问题。具体看下面例子。
假设操作前global值为5。
线程1 线程2
movl global,%eax;global值为5,%eax值为5
addl $1,%eax;%eax值为6
------此时线程2获取执行权限--------->
movl global,%eax;global值为5,%eax值为5
subl $1,%eax;%eax值为4
movl %eax,global;%eax值为4,global值为4
<--------执行权交回线程1--------------
movl %eax,global;%eax值为4,global值为4
由上述例子可以看出,结果并非我们预计的global的值加1减1后仍保持原值,而是由5变为了4。这就是多线程下非原子操作有可能产生的问题。
所以题目global输出并非0一种可能。global的加减操作有可能失效,所以global的结果应分布在-10到10之间。