2013-11-15 28 views
0

考慮下面的例子:例如關於內存排序在C++

-Thread 1- 
y.store (20, memory_order_relaxed); 
x.store (10, memory_order_release); 

-Thread 2- 
if (x.load(memory_order_acquire) == 10) { 
    assert (y.load(memory_order_relaxed) == 20) 
    y.store (10, memory_order_release) 
} 

-Thread 3- 
if (y.load(memory_order_acquire) == 10) 
    assert (x.load(memory_order_relaxed) == 10) 

在這個例子中第二assert必火(對嗎?)。是否因爲在y.store (10, memory_order_release)之前線程2中沒有存儲到x

(在cppreference.com中,他們說這個關於release的句子:「使用此內存順序的存儲操作執行釋放操作:對其他內存位置的先前寫入對於在其上執行消耗或獲取的線程變得可見位置「。)

我可以在線程2中將y的存儲順序從release改爲sec/cst以解決問題嗎?

+0

沒有'assert'可以觸發..有趣的是,即使thread2中'y'的存儲順序改變爲'relaxed',仍然沒有'assert'可以觸發,因爲這不會破壞發生的鏈 - 之前事件(線程3仍然需要使用'acquire') – LWimsey

回答

2

由於您尚未指定x & y的初始值,因此您的示例不完整。但假設啓動所有線程的線程已初始化爲0.

然後,如果線程2對y執行存儲,則它必須從線程1的存儲區讀取到x並與其同步。如果線程3從y讀取線程2的存儲到y,它也必須同步。因此,線程1中x的存儲必須發生在線程3中的加載之前,並且它必須在初始化存儲到x後發生。因此,線程3的x.load必須得到值10.在沒有消耗之前發生的是傳遞。

我建議在這些示例中使用CDSChecker來查看可能的值。

+0

查看http://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync總體總結部分的示例,他們說第二個斷言將觸發。 – MRB

+0

GCC示例聲明不同的內存排序,所以它不相關。 – briand