i 和 i 是否為原子操作?

2021-10-19 18:15:32 字數 1687 閱讀 2595

2023年02月22日 周一 天氣晴 【不悲嘆過去,不荒廢現在,不懼怕未來】

參考文獻

原子操作是不可分割的,在執行完畢前不會被任何其它任務或事件中斷:

在單執行緒中, 能夠在單條指令中完成的操作都可以認為是 原子操作,不能在單條指令中完成的操作也都可以認為不是原子操作,因為中斷可以且只能發生於指令之間;

在多執行緒中,不能被其它程序(執行緒)打斷的操作就叫原子操作;

++i;

00007ff

7d69f17e8 mov eax,dword ptr [i]

00007ff

7d69f17eb inc eax

00007ff

7d69f17ed mov dword ptr [i]

,eax

i++;

00007ff

7d69f17f0 mov eax,dword ptr [i]

00007ff

7d69f17f3 inc eax

00007ff

7d69f17f5 mov dword ptr [i]

,eax

可見,無論是 ++i 還是 i++ ,都是使用三個指令來實現的:

1、將值從記憶體拷貝到暫存器;

2、暫存器自增;

3、將值從暫存器拷貝到記憶體;

所以,++i 和 i++ 都不是原子操作。

由上可知,i++ 是由3條指令構成的運算操作,兩個執行緒在 i 變數上共計需要執行100(次迴圈)*3(條指令)*2(個執行緒)= 600條指令,這600條指令在某種排列下會導致最終i的值僅為2。

假設兩個執行緒的執行步驟如下,最終 i 的值僅為2:

執行緒a執行第一次i++,取出記憶體中的i,值為0,存放到暫存器後執行加1,此時cpu1的暫存器中值為1,記憶體中為0;

執行緒b執行第一次i++,取出記憶體中的i,值為0,存放到暫存器後執行加1,此時cpu2的暫存器中值為1,記憶體中為0;

執行緒a繼續執行完成第99次i++,並把值放回記憶體,此時cpu1中暫存器的值為99,記憶體中為99;

執行緒b繼續執行第一次i++,將其值放回記憶體,此時cpu2中的暫存器值為1,記憶體中為1;

執行緒a執行第100次i++,將記憶體中的值取回cpu1的暫存器,並執行加1,此時cpu1的暫存器中的值為2,記憶體中為1;

執行緒b執行完所有操作,並將其放回記憶體,此時cpu2的暫存器值為100,記憶體中為100;

執行緒a執行100次操作的最後一部分,將cpu1中的暫存器值放回記憶體,記憶體中值為2;

結果為200的情況相對簡單,只需要兩個執行緒間隔操作即可。

兩個執行緒分別記為執行緒1和執行緒2,i++相當於取出i的值,加1,再放回去

第一種極端情況:每次執行緒一取出i的值後cpu時間切換到執行緒二,執行緒二也取出i的值,取到的值和執行緒一相等,執行緒二給i加一後放回去,執行緒一也將i加一後放回去,放回去的值也相等,相當於兩個執行緒都執行一次i++操作,i的值只增加1,這樣操作100次i的值為100

第二種極端情況:執行緒一和執行緒二間隔操作,即執行緒一對i++操作完成,把已經加一的資料放回去之後執行緒二再操作,輪流進行,最後每個執行緒都對i加了100次,i的值為200

i++(++i)不是原子操作

程序有乙個全域性變數i,還有有兩個執行緒。i++在兩個執行緒裡邊分別執行100次,能得到的最大值和最小值分別是多少?

i 是原子操作嗎?

原子操作 是不可被中斷的 i 不是原子操作 分為3步 1 先從記憶體中把i取出來放到暫存器中 2 然後 3 然後再把i複製到記憶體中,這需要至少3步 1.什麼是作業系統的 原子操作 原子操作是不可分割的,在執行完畢不會被任何其它任務或事件中斷,分為兩種情況 兩種都應該滿足 1 在單執行緒中,能夠在單...

i 是不是原子操作

可能我們對i 或者 i的用法已經爛熟於心,但是有次去浦發面試,面試官問,i 是不是原子操作,當是問懵了,回來惡補一下 問這個問題,面試官是想考察你對記憶體的理解。首先,之所以要討論是不是原子操作,因為如果是原子操作的話,在多執行緒操作時,就不用為了保護這個操作而加上昂貴又耗費效能的鎖。在單核作業系統...

i 是原子操作嗎

什麼是原子操作?所謂原子操作,就是 不可中斷的乙個或一系列操作 在確認乙個操作是原子的情況下,多執行緒環境裡面,我們可以避免僅僅為保護這個操作在外圍加上效能開銷昂貴的鎖。那麼,gnu c中x 是原子操作嗎?請看下面一段 cpp view plain copy print?include includ...