什么是放松对ThreadMethodOne中的加载变量valA和valB的同步的最正确方法(假设valA和valB没有错误的缓存行共享)?似乎我不应该改变ThreadMethodOne使用memory_order_relaxed来加载valA,因为编译器可能会在valB.load之后移动valA.load,因为valB.load上的memory_order_acquire不能保护valA不会在valB.load之后移动一次这一变化已经完成。它似乎也不能在valB.load上使用memory_order_relaxed,因为它不再与ThreadMethodTwo中的fetch_add同步。交换项目并放宽valA的负载会更好吗?C++在两个不同的变量上使用memory_order_relaxed
这是正确的改变吗?
nTotal += valB.load(std::memory_order_acquire);
nTotal += valA.load(std::memory_order_relaxed);
纵观上编译器Explorer中的结果似乎显示ThreadMethodOne相同的代码生成时使用memory_order_relaxed对于任何瓦拉或值Valb,即使我不换的指令的顺序。我还看到ThreadMethodTwo中的memory_order_relaxed仍编译为与memory_order_release相同。将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 关于这个问题的权威性讨论。 –