2009-10-18 28 views
3

顯然,原子操作可以確保不同的線程不會破壞值。但是,在使用共享內存的過程中,這仍然是真的嗎?即使這些進程恰巧被操作系統安排在不同的內核上運行?或跨越不同的CPU?跨進程的原子操作是否與跨線程一樣工作?

編輯:另外,如果它不安全,即使在像Linux這樣的操作系統上,從調度程序的角度來看進程和線程是相同的,它是不是安全的?

回答

3

tl; dr:閱讀原子操作文檔中的細則。有些將按設計原子化,但可能會超過某些變量類型。但是,一般來說,原子操作會像在線程之間那樣維護不同進程之間的契約。

原子操作確實只能確保在兩個實體同時調用時不會出現不一致狀態。例如,通過在相同的整數兩個不同的線程或進程被稱爲原子增量將總是表現像這樣:

  1. X =初始值(零爲了討論起見)
  2. 實體A的增量x和結果返回到本身:結果= X = 1。
  3. 實體B x遞增並將結果返回到本身:結果= X = 2

其中A和B表示第一和第二螺紋或進行呼叫的進程。

可導致由於競爭條件不一致或大致瘋狂結果的非原子操作時,不完整的寫入地址空間,等等。例如,可以很容易地看到:

  1. X =初始值再次爲零。要評估x + 1,A檢查x(零)的值並添加1.實體B調用x = x + 1。爲了評估x + 1,B檢查x的值(仍爲零)並加1. 1.實體B(由運氣)首先完成並將x + 1 = 1(步驟3)的結果賦給x。 x現在爲1.
  2. 實體A完成第二個並將x + 1 = 1(步驟2)的結果分配給x。 x現在爲1.

注意競爭條件爲實體B比賽過去A,並首先完成表達式。

現在想象一下,如果x是一個64位double,並且不能保證有原子分配。在這種情況下,你可以很容易看到這樣的內容:

  1. 64位雙x = 0的
  2. 實體A試圖分配0x1122334455667788爲x。首先分配前32位,將0x1122334400000000留給x。
  3. 實體B進入並將0xffeeddccbbaa9988分配給x。偶然的情況是,這兩個32比特的一半都被更新,並且x現在= 0xffeeddccbbaa9988。
  4. 實體A在下半部分完成其分配,x現在= 0xffeeddcc55667788。

這些非原子分配是您需要診斷的最可怕的併發錯誤。