zamawianie pamięci za pomocą blokady spinowej atomic_flag
Próbuję zapoznać się z nowymi koncepcjami zamawiania pamięci c ++ 11 i wierzyłem, że naprawdę dobrze się z nimi zapoznałem, aż natknąłem się na implementację blokady spinowej:
#include <atomic>
namespace JayZ
{
namespace Tools
{
class SpinLock
{
private:
std::atomic_flag spin_lock;
public:
inline SpinLock( void ) : atomic_flag( ATOMIC_FLAG_INIT ) {}
inline void lock( void )
{
while( spin_lock.test_and_set( std::memory_order_acquire ) )
;
}
inline void unlock( void )
{
lock.clear( std::memory_order_release );
}
};
}
}
To jest np. ekwiwalentnie wspomniany whttp://en.cppreference.com/w/cpp/atomic/atomic_flag
a także w książce „Concurrency in Action”. Znalazłem to także gdzieś tutaj w SO.
Ale po prostu nie rozumiem, dlaczego to zadziała!
Wyobraź sobie, że wątek 1 wywołuje lock (), a test_and_set () zwraca 0, ponieważ stara wartość -> wątek 1 uzyskał blokadę.
Ale potem pojawia się wątek 2 i próbuje tego samego. Teraz, gdy nie wystąpił żaden „synchronizacja sklepu” (wydanie, seq_cst_acq_rel), wątek 1 sklepu do spin_lock powinien być typu zrelaksowanego.
Ale z tego wynika, że nie można zsynchronizować z odczytem spin_lock wątku 2. Powinno to umożliwić wątkowi 2 odczytanie wartości 0 z spin_lock, a tym samym uzyskanie blokady.
Gdzie jest mój błąd?