0715デフォルトの名無しさん
2018/12/19(水) 10:08:12.65ID:Yvire5cbatomic fence は、二つのスレッドが同時に読み書きすることを防ぐ目的で使うもの。
たとえば、グローバル変数 a に「1足す」場合、CPUは、それをいったん(内部)
レジスタなどに読み取ってから、1足し、最後に同じグローバル変数 a に書き戻す。
この際、二つのスレッドがほぼ同時に「読んで」しまった場合、合計で「2」を足して欲しいのに、「1」しか足されなくなってしまう。それを防ぐために、ある同時に「読む」ことすら防ぐフェンスのようなものを用意するためのもの。だから、専用APIとして、
InterlockedIncrement() があったり、CPU自体にもマシン語レベルでLOCK修飾なるもの
があったりする。
一方、SetEvent() などのイベント発生を「待つ」ことは、この仕組みだけでは不十分で、
次のような単純なやり方では CPU がフルパワー状態になり、電力の無駄使いになる。
ちなみに、このように (HLT 命令を使っていない) BUSY LOOP では、CPU の 電力消費
が何十倍にもなることがある(だから、sleep()命令は特殊な実装を行ってる)。:
ATOMIC_FENC g_fence;
BOOL g_bEvnet = 0;
void mySetEvent() // スレッドBが使うとする。
{
g_bEvent = 1;
}
void myWaitForEvent() // スレッドAが使うとする。
{
// 以下ループで、CPUがフルパワー状態になり電気の無駄使いになる:
for ( ;; ) {
BeginAtomicFence(&g_fence); // あなたが言ったAtomic Fenceの開始。
if ( !g_bEvent ) {
g_bEvent = 0;
EndAtomicFence(&g_fence); // あなたが言ったAtomic Fenceの終了。
break;
}
EndAtomicFence(&g_fence); // あなたが言ったAtomic Fenceの終了。
}
}