[英]C++ memory ordering
在一些教程中,我看到了這樣的自旋鎖實現
class spin_lock
{
atomic<unsigned int> m_spin ;
public:
spin_lock(): m_spin(0) {}
~spin_lock() { assert( m_spin.load(memory_order_relaxed) == 0);}
void lock()
{
unsigned int nCur;
do { nCur = 0; }
while ( !m_spin.compare_exchange_weak( nCur, 1, memory_order_acquire ));
}
void unlock()
{
m_spin.store( 0, memory_order_release );
}
};
我們是否真的需要memory_order_acquire
/ memory_order_release
標簽分別用於compare_exchange_weak
和store
操作? 或者memory_order_relaxed
在這種情況下就足夠了,因為沒有Synchronizes-With關系?
更新:謝謝您的解釋! 我正在考慮spin_lock,沒有使用它的上下文。
是的memory_order_acquire
/ memory_order_release
是必需的。
您使用鎖來保護多個線程之間的共享數據。 如果在unlock
方法中不使用memory_order_release
,則可以在unlock
方法后重新排序對共享數據的任何寫入。 此外,如果您在lock
方法中不使用memory_order_acquire
,則可以在lock
方法之前重新排序對共享數據的任何讀取。 所以你需要acquire/release
來保護線程之間的共享數據。
spinLock.lock() // use acquire here, so any read can't reordered before `lock`
// Writes to shared data
spinLock.unlock() // use release here, so any write can't reordered after `unlock`
使用acquire/release
對鎖定自旋鎖的線程可以看到對共享數據的所有寫入。
關於memory_order_acquire / memory_order_release:考慮使用鎖保護的共享數據(也稱為內存位置或資源)。 我稱之為“受保護的數據”。
代碼需要確保當lock()返回時,調用者對受保護數據的任何訪問都將讀取有效值(即不是過時值)。 memory_order_aquire確保插入適當的aquire內存屏障,以便后續讀取受保護數據(通過本地CPU緩存)將是有效的。 類似地,當調用unlock()時,需要memory_order_release以確保插入適當的內存屏障,以便正確同步其他緩存。
某些處理器不需要獲取/釋放障礙,並且對於理論示例,可能僅需要lock()中的完整屏障。 但是C ++並發模型需要足夠靈活以支持許多不同的處理器體系結構。
memory_order_relaxed在析構函數中使用,因為這只是一個完整性檢查,以確保當前不保持鎖。 破壞鎖定不會給調用者帶來任何同步語義。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.