且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Java volatile变量的行为不正确。

更新时间:2021-07-18 00:18:02


任何人都可以解释为什么它在这里不起作用?由于我被声明为volatile,因此应该保护它不受内存不一致的影响。

Can anyone explanation why it doesn't work here? Since i is declared volatile, it should be protected from memory inconsistency.

它受到保护但不幸的是 i ++ 不是原子操作。它实际上是读/增/存。所以 volatile 不会让你免于线程之间的竞争条件。您可以从程序中获得以下操作顺序:

It is protected but unfortunately i++ is not an atomic operation. It is actually read/increment/store. So volatile is not going to save you from the race conditions between threads. You might get the following order of operations from your program:


  1. 线程#1读取 i ,得到10

  2. 之后,第2号线读取 i ,得到10

  3. 线程#1增量 i 到11

  4. 线程#2增量 i 到11

  5. 线程#1将11存储到 i

  6. 线程#2将11存储到 i

  1. thread #1 reads i, gets 10
  2. right afterwards, thread #2 reads i, gets 10
  3. thread #1 increments i to 11
  4. thread #2 increments i to 11
  5. thread #1 stores 11 to i
  6. thread #2 stores 11 to i

正如您所看到的,即使已经发生了2次增量,值已在线程之间正确同步,竞争条件意味着该值仅上升1.请参阅漂亮的解释。这是另一个很好的答案: Java线程安全中的volatile int?

As you can see, even though 2 increments have happened and the value has been properly synchronized between threads, the race condition means the value only went up by 1. See this nice looking explanation. Here's another good answer: Is a volatile int in Java thread-safe?

你应该使用的是 AtomicInteger ,它允许你从多个线程安全地增加。

What you should be using are AtomicInteger which allows you to safely increment from multiple threads.

static final AtomicInteger i = new AtomicInteger(0);
...
        for (int j = 0; j<1000000; j++) {
            i.incrementAndGet();
        }