2016-11-17 66 views
3

考慮一個fetch_add與acq_rel內存爲了

std::atomic<int> x(0); 

讓我們假設我有一個函數執行以下操作:

int x_old = x.fetch_add(1,std::memory_order_acq_rel); 

基礎上description for acquire release memory ordering

memory_order_relaxed操作輕鬆:沒有同步或排序約束,只有原子性需要此操作的(見下文鬆散排序)

memory_order_consume與此存儲器順序加載操作執行對受影響的存儲器位置的消費操作:沒有讀取或在當前線程依賴於當前加載的值可以寫入在此負載之前重新排序。在釋放相同原子變量的其他線程中寫入數據相關變量在當前線程中可見。只有在大多數平臺上,這會影響編譯器優化(參見發佈-消耗以下的訂購)

memory_order_acquire加載操作與此內存順序執行對受影響的存儲位置獲取操作:無閱讀或在當前線程寫入能在此負載之前重新排序。在其他線程的所有寫入該版本的相同的原子變量是在當前線程可見(見發佈 - 採集以下的訂購)

memory_order_release這種記憶順序的存儲操作執行釋放操作:無讀取或寫入當前線程可以在該商店之後重新排序。當前線程中的所有寫操作在獲取相同原子變量的其他線程中都可見(請參見下面的Release-Acquire命令),並且在原子變量中攜帶依賴項的寫入在使用相同原子的其他線程中變爲可見(請參閱Release-Consume訂購如下)。

memory_order_acq_rel該存儲器命令的讀取 - 修改 - 寫入操作既是獲取操作又是釋放操作。在當前線程中沒有內存讀取或寫入可以在該存儲之前或之後重新排序。在其他線程中釋放相同原子變量的所有寫操作在修改之前都是可見的,並且修改在獲取相同原子變量的其他線程中可見。

memory_order_seq_cst與此存儲器順序兩者獲取操作和釋放操作,加上單個總訂單存在其中所有線程觀察以相同的順序的所有修改(見下文按順序一致的排序)

的任何操作

2個不同的線程可能接收相同的x_old值0嗎?或者他們是否保證以x_old爲0的方式執行其中的一個,而另一個是1。

如果x_old對於它們兩個都可能爲0,那麼更改內存順序爲std::memory_order_seq_cst是否保證x_old的唯一性?

+0

內存排序不相關。兩個線程不可能獲得相同的值(假設每個線程只能達到一次表達式)。 – 2501

+0

內存排序爲什麼不重要?難道兩個線程都不能在acq_rel下獲得相同的x_old,因爲讀取 - 修改 - 寫入操作沒有讀取讀取順序? –

+0

訂購在這裏根本就不相關。從fetch_add返回的前兩個值始終爲:0和1,但不能保證哪個線程獲得哪個值。無論您選擇哪種memory_order,情況都是如此。 – 2501

回答

4

2個不同的線程可能接收到相同的x_old值0嗎?

這是不可能的,因爲操作是原子。它要麼全部發生,要麼根本不發生。

訂購與前/後加載/存儲有關,並且由於您沒有任何訂購,因此訂購在此無關緊要。換句話說,x.fetch_add(1, std::memory_order_relaxed);在這裏有相同的效果。

在當前x86上它是相同的lock xadd指令,不管memory_order,lock前綴是否提供原子性和排序。對於memory_order_relaxed,訂購部分lock是不必要的。