为什么局部变量不允许使用volatile关键字



考虑以下代码片段:

如果在主线程中,我在方法-

volatile CountDownLatch latch = new CountDownLatch(3);
new Thread(new ProcessThread("Worker1",latch, 20000)).start();//20 secs
new Thread(new ProcessThread("Worker2",latch, 60000)).start();//60 secs
new Thread(new ProcessThread("Worker3",latch, 40000)).start();//40 secs

我看到volatile显示为非法修饰符。只有final是允许的。And final保证初始化安全

public static class ProcessThread implements Runnable {
  final CountDownLatch latch;
  final long workDuration;
  final String name;
  public ProcessThread(String name, CountDownLatch latch, long duration){
      this.name= name;
      this.latch = latch;
      this.workDuration = duration;
  }
}

下面的对象即new CountDownLatch(3)是正确构造的,但我也想确保上面对象分配给的引用latch对它下面的代码是可见的。

final CountDownLatch latch = new CountDownLatch(3);

上面的代码是否保证初始化,使latch对下面的代码完全可见,即

new Thread(new ProcessThread("Worker1",latch, 20000)).start();

局部变量驻留在堆栈上;当然,当你两次调用相同的方法时,它们在各自的堆栈上都有所有的局部变量。

volatile仅在多个线程写入相同的内存位置(在堆上)时才有意义。

对于方法体中的局部变量来说是完全没有意义的!

And final保证初始化安全。

局部变量不行:它只会阻止你重新赋值该变量。

final CountDownLatch latch = new CountDownLatch(3);

上面的代码是否保证初始化,使得latch对下面的代码(即

)完全可见?

。这段代码保证了这一点:

public static class ProcessThread implements Runnable {
    final CountDownLatch latch;
    // Plus the assignment in the constructor.
}

final字段保证在构造函数完成后(通常)是可见的。源自JLS第17.5节:

对象在其构造函数完成时被认为已完全初始化。如果一个线程只能在对象完全初始化之后才能看到对该对象的引用,则可以保证看到该对象的final字段的正确初始化值。

本地执行的操作不会有其他线程的可见性或干扰问题,因此声明本地变量volatile没有意义。

最新更新