Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 两个线程访问相同的变量,但一个线程很少发生。非原子学?_C++_Multithreading_X86_Atomic_Memory Fences - Fatal编程技术网

C++ 两个线程访问相同的变量,但一个线程很少发生。非原子学?

C++ 两个线程访问相同的变量,但一个线程很少发生。非原子学?,c++,multithreading,x86,atomic,memory-fences,C++,Multithreading,X86,Atomic,Memory Fences,我有两个线程,t1和t2,它们访问多个变量(int和double),让我们称它们为a、b和c。t1在我的关键路径上,通过昂贵的比较和交换增加/减少这些变量 std::atomic<double> a; std::atomic<double> b; std::atomic<double> c; std::atomic<uint32_t> d; . . . // Extremely-common, critical path thread t1 d++

我有两个线程,t1和t2,它们访问多个变量(int和double),让我们称它们为a、b和c。t1在我的关键路径上,通过昂贵的比较和交换增加/减少这些变量

std::atomic<double> a;
std::atomic<double> b;
std::atomic<double> c;
std::atomic<uint32_t> d;
.
.
.
// Extremely-common, critical path thread t1
d++;
while(!a.compare_and_exchange(expectedVal, newVal);
while(!b.compare_and_exchange(expectedVal, newVal);
while(!c.compare_and_exchange(expectedVal, newVal);
目前我使用原子学有没有办法将变量声明为非原子变量,因为99.999%的时间是从同一个线程递增的,在“稀有线程”上,我可以使用内存屏障来确保在“关键路径”线程完成任何存储写入之前,我不能返回
a+b-c


这将允许我仅在罕见线程偶尔执行的情况下添加延迟。

从您的问题来看,我不确定这是否可行,但您可以重构线程之间的“通信”以共享较少的状态


例如,假设它们仅通过
a+b-c
进行“通信”,即只有t1单独更新组件,而t2仅读取此特定组合。在这种情况下,您可以通过将
a
b
c
定义为常规变量,并将新变量
组合
定义为原子变量来使用更少的原子操作。t1会正常地增加数据量,并使用一个原子op来更新
组合

,所以基本上保持结果缓存,t1会更新缓存的结果?听起来不错。你有什么特别的问题吗?是的,但这不是什么大问题,不是吗?根据这个问题,t2无论如何都不在关键路径上。事实上,只要你有一个单一的交流点,你就可以完全避开原子;问题是,即使没有CA,正确对齐的数据也总是以原子方式读取和写入,因此如果这确实是线程之间唯一的通信点(即,没有其他类似性质的变量),那么在t2中,您将无法区分是否读取了“old”数据只是因为t2在t1放在那里之前请求它,或者因为t2在t1放在那里之后请求它,但在数据传播到t2之前。@没有错误,你可能是对的,但我不太确定。不久前读过Anthony William关于C++11线程的书,我认为可能存在部分读取的问题。
// Rare thread, t2
return a + b - c;