題目:
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之間。
