簡體   English   中英

C ++內存排序

[英]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_weakstore操作? 或者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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM