在匿名线程

时间:2018-01-17 03:40:24

标签: java multithreading concurrency thread-safety visibility

做一些像

这样的事情是否安全
for (int i = 0; i < 10; i++){
  final int finalI = i;
  new Thread(() -> { 
       // use finalI in the thread somehow
       });
}

所以我想问的问题是,是否保证线程0..9会看到finalI分别为0..9?

例如,如果在第二次迭代中finalI被更改并且第一个线程将finalI视为1而不是0,那该怎么办。

我有99%的感觉这是不可能的,但我不知道匿名类如何存储变量,所以我不是百分百肯定。

如果anon类引用了对该变量的外部引用那么那将是错误的,但它实际上并不是一个引用,因为它是一个原语。那么heck如何将线程anon类存储变量?

在幕后,JVM是否会使它在anon线程中给出一个字段私有final int finalI然后隐含地在构造函数中设置它?

1 个答案:

答案 0 :(得分:0)

finalI将分别为0..9。

要了解内部发生的事情,请查看将变量声明为

的内容
  

最终

确实

让我们

public class ThreadTest {

public static void main(String[] args) {
    for(int i =0; i< 9; i++) {
        final int finalI = i;
        new Thread(()->{
            try {
                Thread.sleep(1000); // assuming a delay for some operations
                System.out.println(Thread.currentThread().getName()+" "+finalI);
                //System.out.println(Thread.currentThread().getName()+" "+ i); // can't do this.
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start(); 

    }
}
}

方法的局部变量保留在堆栈中,并在方法结束后立即丢失。即使在方法结束后,即使在本地声明的最终变量/对象也可以被访问,因为它们被其他类/方法引用,在这种情况下它是可运行的。

所以当我们执行

  

final int finalI = i;

我们正在创建一个新的finalI变量,它既不能改变前一个变量,也不能使用这个值,因为之前的finalI是分别放在JVM堆中的。

相关问题