変数valAとvalBの同期をThreadMethodOneのロード時に緩和する最も正しい方法は何ですか(valAとvalBの誤ったキャッシュライン共有がないと仮定します)? valB.loadのmemory_order_acquireはvalB.loadの後にvalAを移動しないように保護していないため、コンパイラはvalB.loadの後にvalA.loadを移動できるため、memory_order_relaxedを使用するようにThreadMethodOneを変更すべきではないようですその変更が行われます。また、valB.loadにmemory_order_relaxedを使用することはできないようです。なぜなら、ThreadMethodTwoのfetch_addと同期しなくなるからです。アイテムを交換してvalAの負荷を緩和する方が良いでしょうか?C++は2つの異なる変数でmemory_order_relaxedを使用しています
これが正しい変更ですか?コンパイラのエクスプローラ上の結果を見ると
nTotal += valB.load(std::memory_order_acquire);
nTotal += valA.load(std::memory_order_relaxed);
は、私は命令の順序を入れ替えていない場合でも、ValaのかvalBのいずれかのためにmemory_order_relaxed使用している場合ThreadMethodOneに同じコード生成を示しているようです。私はまた、memory_order_releaseと同じになるように、ThreadMethodTwoのmemory_order_relaxedがまだコンパイルされていることも確認します。 memory_order_relaxedを次の行に変更すると、ロックされていない 'valA.store(valA.load(std :: memory_order_relaxed)+ 1、std :: memory_order_relaxed);'しかし、これが良いかどうかは分かりません。
全プログラム:
#include <stdio.h>
#include <stdlib.h>
#include <thread>
#include <atomic>
#include <unistd.h>
bool bDone { false };
std::atomic_int valA {0};
std::atomic_int valB {0};
void ThreadMethodOne()
{
while (!bDone)
{
int nTotal {0};
nTotal += valA.load(std::memory_order_acquire);
nTotal += valB.load(std::memory_order_acquire);
printf("Thread total %d\n", nTotal);
}
}
void ThreadMethodTwo()
{
while (!bDone)
{
valA.fetch_add(1, std::memory_order_relaxed);
valB.fetch_add(1, std::memory_order_release);
}
}
int main()
{
std::thread tOne(ThreadMethodOne);
std::thread tTwo(ThreadMethodTwo);
usleep(100000);
bDone = true;
tOne.join();
tTwo.join();
int nTotal = valA.load(std::memory_order_acquire);
nTotal += valB.load(std::memory_order_acquire);
printf("Completed total %d\n", nTotal);
}
それはあなたのコードをクリーンアップした後、コメント
#include <stdio.h>
#include <stdlib.h>
#include <thread>
#include <atomic>
#include <unistd.h>
std::atomic_bool bDone { false };
std::atomic_int valA {0};
std::atomic_int valB {0};
void ThreadMethodOne()
{
while (!bDone)
{
int nTotalA = valA.load(std::memory_order_acquire);
int nTotalB = valB.load(std::memory_order_relaxed);
printf("Thread total A: %d B: %d\n", nTotalA, nTotalB);
}
}
void ThreadMethodTwo()
{
while (!bDone)
{
valB.fetch_add(1, std::memory_order_relaxed);
valA.fetch_add(1, std::memory_order_release);
}
}
int main()
{
std::thread tOne(ThreadMethodOne);
std::thread tTwo(ThreadMethodTwo);
usleep(100000);
bDone = true;
tOne.join();
tTwo.join();
int nTotalA = valA.load(std::memory_order_acquire);
int nTotalB = valB.load(std::memory_order_relaxed);
printf("Completed total A: %d B: %d\n", nTotalA, nTotalB);
}
注文をやり直す必要があるのはなぜですか? – GManNickG
これはトピックをよりよく理解することの問題です。 –
https://www.youtube.com/watch?v=c1gO9aB9nbs 件名に関する決定的な話。 –