给定这样的结构:
struct foo {
atomic_int refcount; /* atomic access */
char* bar1; /* read-only */
char* bar2; /* read-only */
};
严格来说:如果我使用了适当的获取/释放语义,那么bar1
和bar2
是否有必要使用atomic_intptr_t
来保证非原子变量的跨线程可见性?
抽象地说,在原子变量的获取/释放操作之间发生的任何内存操作都将表现为您获取并释放了抽象互斥类型(POSIX、WinAPI等),因为这些操作通常都是这样实现的。原子操作和定义的内存模型的一个主要目标是定义如何围绕原子访问对非原子内存访问进行排序。所以它们不应该是原子的。
如果从不写入指针,那么在初始化结构后只需要一个内存屏障,以确保初始值在其他线程中可见。如果在关键部分更改指针所指的内容,那么获取/发布语义将确保这些更改也可见。
有益的阅读(我不确定C11和C++11的内存模型之间有什么区别):http://en.cppreference.com/w/cpp/atomic/memory_order
http://bartoszmilewski.com/2008/12/01/c-atomics-and-memory-ordering/
编辑:添加了更好的链接。
要迂腐(在谈论内存模型时这是一件好事),没有什么比man更改的日期对其他线程可见。您所能保证的是同步点上发生的事情:如果您的获取读取读取到某个新值,则确保使用发布写入来写入该线程中写入之前的新值的线程的所有效果都已发生并可见。但你实际上并不能保证你的默许者害羞;ing读取将读取新值。
C++11对此稍微更具体一些,并包含一个"注意",即"操作将在有限的时间内对所有其他线程可见"(C++11,1.10/25),但我在C11中没有看到任何类似的语句。
(事实上,我已经在Herb Sutter的原子演讲中发表了一条评论。)