私はメモリバリア/フェンスを使用したプログラミングにかなり慣れていません。セットアップの書き込みが、後で他のCPUで実行されるワーカー関数に表示されることをどのように保証できるのか疑問に思いました。たとえば、次のことを考慮してください。
int setup, sheep;
void SetupSheep(): // Run once
CPU 1: setup = 0;
... much later
CPU 1: sheep = 9;
CPU 1: std::atomic_thread_fence(std::memory_order_release);
CPU 1: setup = 1;
その後(同時にではなく)、何度も何度も実行します。
void ManipulateSheep():
CPU 2: int mySetup = setup;
CPU 2: std::atomic_thread_fence(std::memory_order_acquire);
CPU 2: // Use sheep...
CPU 2では、mySetup
が1の場合、 sheep
9であることが保証されますがmySetup
、0ではないことをどのように保証できますか?
これまでのところ、CPU 2で1になるまでスピンウェイトすることしか考えられません。しかし、スピンウェイトが最初に呼び出されたsetup
ときに待機するだけでよいことを考えると、これは非常に醜いようです。ManipulateSheep()
確かにもっと良い方法があるに違いありませんか?
初期化解除コードには対称的な問題もあることに注意してください。たとえば、存続期間中にメモリを割り当てるロックフリーのデータ構造を作成しているとします。デストラクタでは(すべてのスレッドがメソッドの呼び出しを終了したと仮定して)、すべてのメモリの割り当てを解除する必要があります。つまり、デストラクタを実行しているCPUが最新の変数値を持つ必要があります。デストラクタはそれをチェックするために「最新の」状態が何であるかを知る方法がないため、そのシナリオでスピン待機することさえできません。
編集:私が求めているのは、「すべてのストアが他のCPUに伝播するのを待つ」(初期化の場合)および「すべてのストアがCPUに伝播するのを待つ」(非初期化の場合)と言う方法はありますか?