併發程式設計的原子性隨想
首先了解到併發程式設計有三個性質:原子性,可見性和有序性。
關於原子性,最重要的一個概念是原子性是針對一個操作而言,有點抽象,我是這麼理解的:一個執行緒執行一段程式碼的時候沒有受到其他執行緒執行這段程式碼的影響。
比如,i = 1; 這也是一段程式碼,而且必然是原子性的,因為一個執行緒在給i賦值為1的時候不可能受到其他執行緒的影響。再比如 i ++; 這就不一定是原子性了,因為i ++;這段程式碼的執行其實是分兩步操作的,一步是從主記憶體中將i的值讀到工作記憶體中,另一步是對i加一。一個執行緒在執行這兩步操作的中間可能會受到其它執行緒的影響,比如剛執行完第一步有其他執行緒對i賦值,這就導致再執行第二步執行結果不準確。這只是一個簡單的 i ++,更不用說一段程式碼了,肯定不能保證原子性。
voliate關鍵字可以利用記憶體屏障將工作記憶體中的值及時地重新整理進主記憶體,他保證的是可見性,並不能保證原子性。很好理解,還是 i ++; 就算保證了可見性,這兩步之間還是可能會有其他執行緒再給i賦值,只不過會及時地重新整理進主記憶體及時取到值而已,還是會受到其他執行緒的影響,所以不存在保證原子性。
保證原子性最簡單的方式就是加鎖,保證只有一個執行緒在操作。還有一個CAS無鎖機制,例如AutomicInteger、AutomicBoolean等這類併發包下面的原子類,他們就是利用CAS保證了i+1、b = ture等這些操作的原子性。
說到這裡我還想強調一下一個重要的地方,為什麼前面說:一個執行緒執行一段程式碼的時候沒有受到其他執行緒執行這段程式碼的影響。而不是說:一個執行緒執行一段程式碼的時候沒有其他執行緒也在執行這段程式碼。因為雖然其他執行緒也在執行這段程式碼,但是並不影響。所以voliate並不能保證原子性,但是操作可能是原子性的,即其他執行緒執行對當前執行緒沒有影響,強調保證這個詞。而CAS機制則是保證了不管有多少執行緒一起執行,肯定沒有影響,所以CAS機制可以保證原子性。