i 是不是原子操作

2021-09-26 10:25:46 字數 2029 閱讀 2445

可能我們對i++或者++i的用法已經爛熟於心,但是有次去浦發面試,面試官問,i++是不是原子操作,當是問懵了,回來惡補一下;

問這個問題,面試官是想考察你對記憶體的理解。

首先,之所以要討論是不是原子操作,因為如果是原子操作的話,在多執行緒操作時,就不用為了保護這個操作而加上昂貴又耗費效能的鎖。在單核作業系統中,能夠在乙個指令完成的操作稱為原子操作。

處理器雖然會自動儲存基本的記憶體操作的原子性,但是對於多核cpu的複雜的記憶體操作,處理器是不保證其原子性的,這裡舉個i++的例子,因為它是經典的讀寫改操作:

class main()

while(count != 10);

system.out.println(i);

} public static class mythreed extends threed

++count;

}}}

執行這段**的結果大部分情況下都是1000,這樣i++的操作好像是原子操作的,而這也是我們所期望的值。但是當把迴圈次數增加10倍,100倍甚至更大的時候,每次所得的結果卻都是不一樣的。當我把上述**稍作修改之後:

public static volatile int i = 0;

pulbic static volatile int count = 0;

public static void main(string args)

while(count!=10);

system.out.println(i);

count = 0;

i = 0;

}}public static class mythreed extends threed

}++count;

}}

所得的結果:

同樣的**,只是加了一點其他的操作,結果就大不一樣了,而且把迴圈次數或執行緒數增大,看到的結果更加是五花八門。為什麼會出現這樣的結果呢?其實從這裡可以看出i++確實不是原子操作。

i++做了三次指令操作,兩次記憶體訪問,第一次,從記憶體中讀取i變數的值到cpu的暫存器,第二次在暫存器中的i自增1,第三次將暫存器中的值寫入記憶體。這三次指令操作中任意兩次如果同時執行的話,都會造成結果的差異性。而對於++i,在多核機器上,cpu在讀取記憶體時也可能同時讀到同乙個值,這樣就會同乙個值自增兩次,而實際上只自增了一次,所以++i也不是原子操作。對於上述**中第一次出現的結果,實際上是個原子操作的假象,因為執行緒數量少,迴圈次數也少,加上在執行時,虛擬機器可能會對**做部分優化,所以看起來結果是對的,而當我在**中做一些其他的耗時的操作時,這種假象就不攻自破了。

那麼,如何實現i++和++i的原子性呢?

在多核cpu的複雜記憶體操作中,處理器提供了匯流排鎖和快取鎖兩個機制來保證原子性,可以通過處理器提供的很多lock字首的指令來實現。

匯流排鎖:多個處理器可能會同時從各自的快取中讀取變數,並分別進行操作,在分別寫入記憶體中,想要保證讀改寫共享變數的操作是原子的,就要使用匯流排鎖來解決,即使用處理器提供的乙個lock#訊號,當有乙個處理器在匯流排上輸出此訊號時,其他處理器的請求將被阻塞,此時該處理器可以獨佔共享記憶體。

快取鎖:頻繁使用的記憶體將會快取在處理器的快取記憶體裡,記憶體區域如果被快取到處理器的快取行裡,並且在lock操作期間被鎖定,那麼當他執行鎖操作回寫到記憶體時,其他處理器會檢查各自快取行內的記憶體位址,如果發現自己的快取行對應的位址被修改了,就會將快取行置於無效狀態,下次訪問時,重新從記憶體中讀取資料到快取行,並允許它的快取一致性機制(通常採用嗅探技術來實現,即快取不僅僅是在記憶體傳輸的時候才和匯流排打交道,而是時刻不停的在窺探匯流排上發生的資料交換,並跟蹤其他快取在做什麼,所以當乙個快取代表它所屬的處理器去讀寫記憶體時,其他處理器都會得到通知,從而保證各個快取保持同步)來保證操作的原子性。此時,處理器不會在匯流排上輸出lock#訊號。

匯流排鎖會把cpu和記憶體之間的通訊鎖住,導致其他處理器不能操作其他記憶體位址的資料,所以匯流排鎖的開銷比較大,在某些場合下,會使用快取鎖來代替匯流排鎖進行優化。

但是,當操作的資料不能被快取在處理器內部或要操作的資料會跨多個快取行時,處理器會呼叫匯流排鎖。對於有些處理器不支援快取鎖,就算鎖定的記憶體區域在處理器的快取行,這時也會呼叫匯流排鎖。

i 是原子操作嗎?

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

i 是原子操作嗎

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

i 和 i 是否為原子操作?

2021年02月22日 周一 天氣晴 不悲嘆過去,不荒廢現在,不懼怕未來 參考文獻 原子操作是不可分割的,在執行完畢前不會被任何其它任務或事件中斷 在單執行緒中,能夠在單條指令中完成的操作都可以認為是 原子操作,不能在單條指令中完成的操作也都可以認為不是原子操作,因為中斷可以且只能發生於指令之間 在...