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

Shi*_*han 5 java multithreading final 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
Run Code Online (Sandbox Code Playgroud)

我看到它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;
  }
}
Run Code Online (Sandbox Code Playgroud)

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

final CountDownLatch latch = new CountDownLatch(3);
Run Code Online (Sandbox Code Playgroud)

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

new Thread(new ProcessThread("Worker1",latch, 20000)).start();
Run Code Online (Sandbox Code Playgroud)

Gho*_*ica 10

局部变量存在于堆栈中; 当然,当你调用相同的方法两次,他们对自己的个人堆栈的局部变量.

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

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

  • 我想安迪在那里打败了我; 但你是对的; 我有点忽略了那个方面. (2认同)

And*_*ner 2

而final保证了初始化的安全性。

不适用于局部变量:它只会阻止您重新分配该变量。

final CountDownLatch latch = new CountDownLatch(3);
Run Code Online (Sandbox Code Playgroud)

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

不,是这段代码保证了这一点:

public static class ProcessThread implements Runnable {

    final CountDownLatch latch;

    // Plus the assignment in the constructor.

}
Run Code Online (Sandbox Code Playgroud)

final一旦构造函数完成(通常),字段就保证可见。来自JLS 第 17.5 节

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