首页 文章

C 11是否保证发布栏和消费操作之间的内存排序?

提问于
浏览
9

请考虑以下代码:

struct payload
{
    std::atomic< int > value;
};

std::atomic< payload* > pointer( nullptr );

void thread_a()
{
    payload* p = new payload();
    p->value.store( 10, std::memory_order_relaxed );
    std::atomic_thread_fence( std::memory_order_release );
    pointer.store( p, std::memory_order_relaxed );
}

void thread_b()
{
    payload* p = pointer.load( std::memory_order_consume );
    if ( p )
    {
        printf( "%d\n", p->value.load( std::memory_order_relaxed ) );
    }
}

C是否对线程a中的fence与线程b中的consume操作的交互做出了任何保证?

我知道在这个例子中我可以用商店版本替换fence原子商店并让它工作 . 但我的问题是关于使用栅栏的这种特殊情况 .

阅读标准文本我可以找到关于释放围栏与获取围栏的交互以及具有获取操作的释放围栏的交互的条款,但没有关于释放围栏和消费操作的交互的内容 .

我认为,用一个获取取代消费将使代码符合标准 . 但据我了解处理器实现的内存排序约束,我应该只需要线程b中较弱的“消耗”排序,因为内存屏障强制线程a中的所有存储在存储到指针之前可见,并且读取有效负载取决于从指针读取 .

标准是否同意?

1 回答

  • 1

    你的代码有效 .

    我知道在这个例子中我可以用商店版本替换fence原子商店并让它工作 . 但我的问题是关于使用栅栏的这种特殊情况 .

    放松原子操作的栅栏比相应的原子操作 stronger . 例如 . (来自http://en.cppreference.com/w/cpp/atomic/atomic_thread_fence,注释):

    虽然原子存储释放操作会阻止所有先前的写操作移过存储释放,但具有memory_order_release排序的atomic_thread_fence会阻止所有先前的写操作移过所有后续存储 .

相关问题