简体   繁体   English

必须在多大程度上使用原子类型来保证跨线程可见性?

[英]To what extent must atomic types be used to guarantee cross-thread visibility?

Given a structure like this: 给定这样的结构:

struct foo {
    atomic_int refcount; /* atomic access */
    char* bar1;          /* read-only */
    char* bar2;          /* read-only */
};

Strictly speaking: is it be necessary to use atomic_intptr_t for bar1 and bar2 to guarantee cross-thread visibility of the non-atomic variables, granted that I use proper acquire/release semantics? 严格来说:是否有必要使用atomic_intptr_t作为bar1bar2来保证非原子变量的跨线程可见性,授予我使用正确的获取/释放语义?

Taken abstractly, any memory operations that occur between the acquire/release operations on the atomic variable will behave as if you had acquired and released an abstract mutex type (POSIX, WinAPI, etc), since that's how these are generally implemented anyway. 抽象地说,在原子变量上的获取/释放操作之间发生的任何内存操作都会表现得就像你已经获得并发布了一个抽象互斥类型(POSIX,WinAPI等),因为无论如何通常都会实现这些操作。 A major goal of atomic operations and a defined memory model is to define how non-atomic memory accesses are ordered around atomic accesses. 原子操作和定义的内存模型的主要目标是定义如何在原子访问周围对非原子内存访问进行排序。 So they should not need to be atomic. 所以他们不应该是原子的。

If you never write to the pointers, then you only need a memory barrier after initialization of the struct to ensure that the initial values become visible in other threads. 如果您从不写指针,那么在初始化结构之后只需要一个内存屏障,以确保初始值在其他线程中可见。 If in your critical section you mutate what the pointers refer to, the acquire/release semantics will ensure that those changes become visible as well. 如果在您的关键部分中您改变了指针引用的内容,则获取/释放语义将确保这些更改也变得可见。

Helpful reading (I'm not sure of any differences between C11 and C++11's memory model): http://en.cppreference.com/w/cpp/atomic/memory_order 有用的阅读(我不确定C11和C ++ 11的内存模型之间有什么区别): http//en.cppreference.com/w/cpp/atomic/memory_order

http://bartoszmilewski.com/2008/12/01/c-atomics-and-memory-ordering/ http://bartoszmilewski.com/2008/12/01/c-atomics-and-memory-ordering/

EDIT: Added better link. 编辑:添加更好的链接。

To be pedantic (which is a good thing when talking about memory models), there is nothing that mandates that changes ever become visible to other threads. 要学究(谈论内存模型时,这是一件好事),没有什么任务,改变以往任何时候都成为可见的其他线程。 All you are guaranteed is that what happens at a synchronization point: If your acquiring read reads a certain, new value, then you are guaranteed that all the effects of the thread that used a release-write to write that new value which came before the write in that thread have happened and are visible. 所有你得到保证的是在同步点发生的事情: 如果你的获取读取读取某个新值, 那么你可以保证使用release-write的线程的所有效果都能写出之前的新值。写入该线程已经发生并且可见。 But you don't actually have a guarantee that your acquiring-read will ever read the new value. 但你实际上并没有你获得阅读的将读过的新价值方面的保证。

C++11 is mildly more specific about this and contains a "Note" that an "operation will become visible to all other threads in a finite period of time" (C++11, 1.10/25), but I don't see any analogous statement in C11. C ++ 11稍微具体一点,并且包含一个“注意”,“操作将在有限的时间内对所有其他线程可见”(C ++ 11,1.10 / 25),但我不是在C11中看到任何类似的陈述。

(I've actually posted a comment to that effect on Herb Sutter's atomic talk .) (实际上,我已经对Herb Sutter的原子论话发表了评论。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM