C ++ memory ordering

In some tutorial, I saw this implementation of spin lock

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 );
    }
};

Do we really need memory_order_acquire/ tags memory_order_releasefor operations compare_exchange_weakand storeaccordingly? Or is it memory_order_relaxedenough in this case, since there is no synchronization with the relation?

Update: Thanks for the explanation! I considered spin_lock without the context in which it is used.

+4
source share
2 answers

Regarding memory_order_acquire / memory_order_release: look at the general data (memory cells or aka resource) that you use to protect the lock. I will call it "secure data."

, lock() (.. ). memory_order_aquire , , ( ) . , unlock(), memory_order_release , , .

/, lock(). ++ concurrency , .

memory_order_relaxed , , , . .

+3

memory_order_acquire/memory_order_release.

. memory_order_release unlock, unlock. , memory_order_acquire lock, 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 , .

+10

All Articles