確かに、メモリバリアでは、読み取りで最新の値が表示されることを保証できません。それが行うことは、単一のスレッド上とスレッド間の両方で、操作間で順序付けを強制することです。
たとえば、スレッドAが一連のストアを実行してから、フラグの場所への最終ストアの前にリリースバリアを実行し、スレッドBがフラグの場所から読み取り、他の値を読み取る前に取得バリアを実行すると、他の変数はスレッドAによって値が保存されている:
// initially x=y=z=flag=0
// thread A
x=1;
y=2;
z=3;
release_barrier();
flag=1;
// thread B
while(flag==0) ; // loop until flag is 1
acquire_barrier();
assert(x==1); // asserts will not fire
assert(y==2);
assert(z==3);
もちろん、ロードとストア先flag
がアトミックであることを確認する必要があります(変数が適切に配置されている場合、単純なロードとストアの命令は最も一般的なCPUにあります)。スレッドBでwhileループがないと、スレッドBはの古い値(0)を読み取る可能性がありflag
、したがって、他の変数で読み取られる値を保証することはできません。
したがって、フェンスを使用して、デッカーのアルゴリズムで同期を強制することができます。
C ++での実装例を次に示します(C ++ 0xアトミック変数を使用)。
std::atomic<bool> flag0(false),flag1(false);
std::atomic<int> turn(0);
void p0()
{
flag0.store(true,std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
while (flag1.load(std::memory_order_relaxed))
{
if (turn.load(std::memory_order_relaxed) != 0)
{
flag0.store(false,std::memory_order_relaxed);
while (turn.load(std::memory_order_relaxed) != 0)
{
}
flag0.store(true,std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
}
}
std::atomic_thread_fence(std::memory_order_acquire);
// critical section
turn.store(1,std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_release);
flag0.store(false,std::memory_order_relaxed);
}
void p1()
{
flag1.store(true,std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
while (flag0.load(std::memory_order_relaxed))
{
if (turn.load(std::memory_order_relaxed) != 1)
{
flag1.store(false,std::memory_order_relaxed);
while (turn.load(std::memory_order_relaxed) != 1)
{
}
flag1.store(true,std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
}
}
std::atomic_thread_fence(std::memory_order_acquire);
// critical section
turn.store(0,std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_release);
flag1.store(false,std::memory_order_relaxed);
}
完全な分析については、http://www.justsoftwaresolutions.co.uk/threading/implementing_dekkers_algorithm_with_fences.htmlにある私のブログエントリを参照してください。