我是专门从内存模型的角度来问的。 http://en.cppreference.com/w/cpp/atomic/memory_order
我问是因为我想知道我是否可以在下面使用std::memory_order_consume
:
mLocalMemPtr1和2以及mAtomicMemPtr是指向共享缓冲区的指针。
在生产者线程中,我正在做:
for (int x = 0; x < 10; ++x)
{
++mLocalMemPtr1
*mLocalMemPtr1 = x; // <========= A
mAtomicMemPtr.store(mLocalMemPtr1, std::memory_order_release);
}
并在消费者中:
tempMemPtr = mAtomicMemPtr.load(std::memory_order_consume);
while (tempMemPtr != mLocalMemPtr2)
{
++mLocalMemPtr2;
int test = *mLocalMemPtr2; // <======== B
doSomeLongRunningThing(test);
tempMemPtr = mAtomicMemPtr.load(std::memory_order_consume);
}
那么,依赖链会进入tempMemPtr-> mLocalMemPtr2-> test-> doSomeLongRunningThing吗?
我特别担心
B
可能在A
之前执行。我知道我可以使用std::memory_order_acquire
,但是如果条件语句导致了内存顺序依赖性,那么我可以使用consumption(更轻量级)。 最佳答案
CppReference:
1.10.10:
1.10.9:
基于这些事实,我说mLocalMemPtr2
应该同步。但是,仍然存在评估顺序的问题。
if (atomic.load(std::consume) < x)
未指定先评估哪个。无法保证(因为我在标准中找不到),编译器将首先执行消耗操作,刷新共享缓冲区,然后加载atomic
和 x
。尚未找到证明操作数是以“虚假”方式求值的证据,我说的是,如果不对原子负载
mLocalMemPtr2
进行显式分解,它将无法正常工作,CPU可能会读取mLocalMemPtr2
所指向的过时的内存值。 memory_order_acquire
在这里不会有太大变化,因为mLocalMemPtr2
带有数据依赖性。