【发布时间】:2017-02-26 05:51:35
【问题描述】:
我是 Java8 和多线程工作的新手。我在下面尝试了这段代码
public class Test {
public static boolean bchanged = true;
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
while (true) {
if (bchanged != bchanged) {
System.out.println("here");
}
}
}
}
).start();
new Thread((Runnable) () -> {
while (true) {
bchanged = !bchanged;
}
}).start();
}
}
当我运行这段代码时,没有“这里”的打印。但是,当我改变
public static volatile boolean bchanged = true;
然后“这里”将被打印出来。
我最初的推论是,lambda 将具有布尔值的本地副本,并且当它不是 volatile 时它不会影响另一个线程,但是当我尝试在两个线程中打印出布尔值时,它证明我错了。所以在这种情况下我很困惑,volatile 如何影响 lambda 的工作方式。
【问题讨论】:
-
Lambda 与 volatile 字段无关。请阅读这个问题:stackoverflow.com/questions/4885570/…
-
当其他人说你的问题不是关于 lambdas 时,他们试图告诉你 lambda 表达式只是定义匿名内部类的简写方式,并且创建该类的实例。类或实例没有什么特别之处:它们遵循与定义的内部类和以普通方式创建的实例完全相同的规则。在您的情况下,内部类实现了
Runnable,但Runnable也没有什么神奇之处。您所询问的魔法之所以发生,是因为您的代码由多个线程执行。 -
捕获规则正是为了避免这种混淆:如果你可以修改变量,lambda表达式(或内部类)不能通过保持旧值的不变副本来实现。因此,字段可以更改并且不按值捕获,而 局部变量 按值捕获并且必须保持不变,请阅读(有效)
final。
标签: java multithreading java-8 race-condition volatile