顺序一致性和原子性之间有什么区别?

8 c++ java atomic volatile

我读到java volatile是顺序一致但不是原子的.对于atomicity java提供了不同的库.

有人可以用简单的英语解释两者之间的差异吗?

(我相信问题范围包括C/C++,因此添加这些语言标签以吸引更多的观众.)

ass*_*ias 7

想象一下这两个变量在一个类中:

int i = 0;
volatile int v = 0;
Run Code Online (Sandbox Code Playgroud)

而这两种方法

void write() {
    i = 5;
    v = 2;
}

void read() {
    if (v == 2) { System.out.println(i); }
}
Run Code Online (Sandbox Code Playgroud)

volatile的语义保证read将打印5或不打印(假设当然没有其他方法正在修改字段).如果v不是易变的,read也可以打印0因为i = 5并且v = 2可以重新排序.我想这就是顺序一致性的意思,它具有更广泛的含义.

另一方面,volatile不保证原子性.因此,如果两个线程同时调用此方法(v是相同的volatile int):

void increment() {
    v++;
}
Run Code Online (Sandbox Code Playgroud)

你不能保证v会增加2.这是因为v++实际上是三个语句:

load v;
increment v;
store v;
Run Code Online (Sandbox Code Playgroud)

并且由于线程交错,v只能递增一次(两个线程都将加载相同的值).


JB *_*zet 5

假设你有这两个变量:

public int a = 0;
public volatile int b = 0;
Run Code Online (Sandbox Code Playgroud)

假设有一个线程

a = 1;
b = 2;
Run Code Online (Sandbox Code Playgroud)

如果另一个线程读取这些值并看到b == 2,那么它保证也会看到== 1.

但是读取线程可以看到a == 1并且b == 0因为两个写入不是原子操作的一部分,所以读取线程可能会看到a在第一个线程分配值之前所做的更改b.

要使这两个写入原子,您需要同步对这两个变量的访问:

synchronized (lock) {
    a = 1;
    b = 2;
}

...

synchronized (lock) {
    System.out.println("a = " + a + "; b = " + b);
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,读线程会看到a == 0b == 0,或a == 1b == 2,但从来没有中间状态.

  • +1,但你并没有真正说"这是顺序一致性"和"这是原子性". (2认同)