局部变量线程安全吗?

Jör*_*mer 0 java multithreading thread-safety

已经有类似的问题,但它没有回答以下问题。众所周知,字段的值不一定在线程之间立即同步。但是局部变量也是这种情况吗?可以抛出 IllegalStateException 吗?

public static void main(String[] args) {
    final Thread mainThread = Thread.currentThread();
    final Integer[] shared = new Integer[1];

    new Thread(new Runnable() {
        @Override
        public void run() {
            shared[0] = 1;
            mainThread.interrupt();
        }
    }).start();

    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        if (shared[0] == null) throw new IllegalStateException("Is this possible?");
    }
}
Run Code Online (Sandbox Code Playgroud)

mer*_*ike 5

实际上,shared所有线程的值都相同。但是 的值shared[0]还涉及读取数组元素,并且该数组元素与字段一样,可能会受到数据竞争的影响。

你确定shared安全吗?

是的,Java 语言规范写道:

局部变量(第 14.4 节)、形式方法参数(第 8.4.1 节)和异常处理程序参数(第 14.20 节)永远不会在线程之间共享,并且不受内存模型的影响。

在 JVM 级别,每个线程都有自己的局部变量。如果匿名类访问封闭方法的局部变量,编译器会重写这段代码,将变量的值作为构造函数参数传递给内部类,内部类会将其存储在一个final字段中(这种重写就是编译器要求这样一个变量是有效的 final 和明确分配的),并将对该变量的所有访问替换为对 final 字段的访问。由于Java 内存模型为 final 字段提供了特殊保证,即使对象引用是通过数据竞争发布的,这种访问也是安全的,前提是此类发布仅在对象完成构造后发生。