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

时间:2016-10-10 07:11:21

标签: java multithreading volatile final

考虑一下代码段:

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

中有这个
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最后保证初始化安全性

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;
  }
}

下面的对象ie new CountDownLatch(3)已正确构建,但我也想确保分配了上述对象的引用latch保证对其下面的代码可见。

final CountDownLatch latch = new CountDownLatch(3);

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

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

3 个答案:

答案 0 :(得分:9)

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

只有当多个线程写入相同内存位置(在堆上)时,

volatile 才有意义。

这对方法体内的局部变量完全没有意义!

答案 1 :(得分:2)

  

最后保证初始化安全。

不在局部变量上:它只是停止重新分配该变量。

final CountDownLatch latch = new CountDownLatch(3);
     

上述代码是否能保证初始化,以便锁存器对下面的代码完全可见,即

没有。这段代码保证了它:

public static class ProcessThread implements Runnable {

    final CountDownLatch latch;

    // Plus the assignment in the constructor.

}
一旦构造函数完成(通常),保证

final个字段可见。来自JLS Sec 17.5

  

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

答案 2 :(得分:0)

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