C++ C+中围栏的定义+;标准[n4713中的原子围栏]

C++ C+中围栏的定义+;标准[n4713中的原子围栏],c++,c++11,c++17,memory-barriers,C++,C++11,C++17,Memory Barriers,[atomics.fences.2]: 如果存在原子操作X和Y,则释放栅栏A与获取栅栏B同步,这两个操作都在某个原子对象M上操作,使得A在X之前排序,X修改M,Y在B之前排序,Y读取由X写入的值,或者由假设的释放序列X中的任何副作用写入的值,如果它是一个释放操作,那么X将是头 因此,潜在的示例代码如下所示: std::atomic<uint32_t> M; //Thread K std::atomic_thread_fence(std::memory_order::release)

[atomics.fences.2]:

如果存在原子操作X和Y,则释放栅栏A与获取栅栏B同步,这两个操作都在某个原子对象M上操作,使得A在X之前排序,X修改M,Y在B之前排序,Y读取由X写入的值,或者由假设的释放序列X中的任何副作用写入的值,如果它是一个释放操作,那么X将是头

因此,潜在的示例代码如下所示:

std::atomic<uint32_t> M;

//Thread K
std::atomic_thread_fence(std::memory_order::release);  // release fence A sequenced before
M.store(1, std::memory_order::relaxed); // operation X: operating on atomic object M

//Thread J
M.load(std::memory_order::relaxed); // operation Y: operating on atomic object M -- reading sequenced before
std::atomic_thread_fence(std::memory_order::acquire); // acquire fence B
std::原子M;
//螺纹K
标准::原子线程围栏(标准::内存顺序::释放);//按之前的顺序释放围栏A
M.store(1,std::memory_order::relaxed);//操作X:操作原子对象M
//螺纹J
M.load(标准::内存_顺序::松弛);//操作Y:操作原子对象M——读取之前的顺序
标准::原子线程围栏(标准::内存顺序::获取);//获取围栏B
问题:


  • 上述代码是否反映了[atomics.fences.2]所说的内容?如果不是,它应该是什么样子

  • 我认为应该在操作X之后对释放栅栏进行排序,因为释放栅栏正试图使先前的存储对其他线程相对于获取栅栏(B)可见,因此获取栅栏B应该在操作Y之前进行排序。否


  • 我没有足够的经验来使用C++线程模型来给出一个明确的答案,但是子问题1可能会使用一点澄清——术语“正确”可能是含糊不清的,并且确切地指明从代码中所需的整体可能会更有帮助。固定的。如果听起来更好,请告诉我。英语不是我的母语……:(“上面的代码是否反映了[atomics.fences.2]所说的?”-是的,在您的代码
    中,释放围栏A
    获取围栏B
    同步。因此,无论在
    释放围栏A
    之前的线程K中执行何种操作,其效果都将通过
    获取围栏B
    之后的线程J中的任何操作得到保证。不确定您想在第二个q中询问什么但请注意定义中的“Y读取X写入的值”。Y无论如何都可以读取X写入的值-Y可以读取在X之前写入的值。例如,如果Y在X发出之前的某个时间出现。或者如果Y在X之后的某个时间出现,但由于缓存,X的效果尚未传播到其他CPU。在这两种情况下,引用的段落都不适用。仅当Y读取在t之前由X写入的值时,才会应用该段落。例如,如果在t之前M的X值为0,X写1,Y读的值也为1,那么你可以确定Y读的是X写的值。同样,引用的段落无意推断,Y读的值是什么-这是段落本身的先决条件,Y读的是X写的值。段落的意图是保证某些值其他变量,甚至是非原子变量。如果其他变量写在线程
    K
    的释放栏之前,线程
    J
    将在获取栏之后读取该变量,那么该读取将返回写在
    线程K
    中的值。这是给定段落的应用示例。我没有对于C++线程模型有足够的经验给出明确的答案,但子问题1可能会使用一点澄清——术语“正确”。可能是不明确的,从整个代码中准确地指定您需要的保证可能会更有帮助。@ζ——感谢您指出。修复。如果听起来更好,请告诉我。英语不是我的母语……:(“上面的代码是否反映了[atomics.fences.2]所说的内容?”-是的,在您的代码
    中,释放围栏A
    获取围栏B
    同步。因此,无论在
    释放围栏A
    之前的线程K中执行何种操作,其效果都将通过
    获取围栏B
    之后的线程J中的任何操作得到保证。不确定您想在第二个q中询问什么但请注意定义中的“Y读取X写入的值”。Y无论如何都可以读取X写入的值-Y可以读取在X之前写入的值。例如,如果Y在X发出之前的某个时间出现。或者如果Y在X之后的某个时间出现,但由于缓存,X的效果尚未传播到其他CPU。在这两种情况下,引用的段落都不适用。仅当Y读取在t之前由X写入的值时,才会应用该段落。例如,如果在t之前M的X值为0,X写1,Y读的值也为1,那么你可以确定Y读的是X写的值。同样,引用的段落无意推断,Y读的值是什么-这是段落本身的先决条件,Y读的是X写的值。段落的意图是保证某些值其他变量,甚至是非原子变量。如果在线程
    K
    中的释放围栏之前写入其他变量,线程
    J
    将在获取围栏之后读取该变量,则该读取将返回在
    线程K
    中写入的值。这是给定段落的应用示例。