volatile关键字似乎没用?

Fin*_*arr -2 java concurrency volatile

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

public class Main implements Runnable {

   private final CountDownLatch cdl1 = new CountDownLatch(NUM_THREADS);
   private volatile int bar = 0;
   private AtomicInteger count = new AtomicInteger(0);

   private static final int NUM_THREADS = 25;

   public static void main(String[] args) {
      Main main = new Main();
      for(int i = 0; i < NUM_THREADS; i++)
         new Thread(main).start();
   }

   public void run() {
      int i = count.incrementAndGet();
      cdl1.countDown();
      try {
         cdl1.await();
      } catch (InterruptedException e1) {
         e1.printStackTrace();
      }
      bar = i;
      if(bar != i)
         System.out.println("Bar not equal to i");
      else
         System.out.println("Bar equal to i");
   }

}
Run Code Online (Sandbox Code Playgroud)

每个Thread进入run方法并通过从被调用者获取值来获取唯一的线程限制int变量.然后每个等待被叫(当最后到达闩锁时,所有被释放).释放锁存器时,每个线程都会尝试将其受限值分配给共享的,被调用的.iAtomicIntegercountThreadCountDownLatchcdl1ThreadThreadsivolatileintbar

我希望Thread除了一个之外的每一个都打印出"Bar not equal to i",但每个都Thread打印出"Bar等于i".呃,wtf确实volatile会这样做,如果不是这样的话?

这是故意的意图,每个人都Thread试图bar在完全相同的时间设置值.

编辑:

根据答案,将代码更改为:

...
bar = i;
try {
    Thread.sleep(0);
} catch(InterruptedException e) {
    e.printStackTrace();
}
...
Run Code Online (Sandbox Code Playgroud)

确保在设置和读取变量之间浪费一点时间.

现在,Bar的相同/不同值的打印为50/50.

Aff*_*ffe 8

JVM决定线程何时运行,而不是你.如果它感觉像握着其中一个闩锁刚刚释放了10ms的那个,那只是因为它可以做到这一点.在闩锁释放后,他们仍然需要等待轮到他们执行.除非你在一台25核计算机上运行它,否则它们并不是在机器内"同时"附近的任何地方分配条形码.由于您所做的只是一些原始操作,因此在下一个释放之前,其中一个不可能在其时间片内完成!