java - Scala 在线程中的“共享”局部变量与 Java 不同吗?它是如何工作的?
问题描述
我对局部变量如何工作的心智模型是它们存储在堆栈上,每个线程都有自己的堆栈,并且线程之间不能访问堆栈。
在 Java 中,我实际上不确定如何在生成的线程中修改局部变量,因为编译器抱怨我无法在 lambda 或内部类中修改它。
但是,在 Scala 中,我可以这样做:
implicit val ec = scala.concurrent.ExecutionContext.global
var i = 5
val f = Future {
println((1, i))
i = 6
println((1, i))
}
val g = Future {
println((2, i))
println((2, i))
println((2, i))
}
Await.result(f, 3.seconds)
并获得结果
(2,5)
(1,5)
(2,5)
(2,6)
(1,6)
线程#2 如何看到线程#1 的修改?
解决方案
你完全正确。每个线程都有自己的堆栈,局部变量驻留在堆栈上。
这就是 Java 局部变量应该是 final 或有效 final 的原因。但是你可以使用一个众所周知的单元素数组技巧,这样指向数组的指针实际上是最终的并且驻留在堆栈上,但是数组的元素可以在闭包中更改。像这样:
int a[] = new a[0];
Thread t = new Thread(() -> {
a[0] = 1;
});
//...
在 Scala 中,编译器会为您做类似的事情,并将它们放在堆上而不是自己的堆栈上。(抱歉,无法编写一个简单的 Scala 示例并立即查看其字节码,但它非常简单易读javap -c
)
推荐阅读
- javascript - 使用数学根据 URL 参数将数字相加?
- c++ - Linux Mint 19 下的 wxWidgets 源代码(.cpp 文件)在哪里提取以进行步入调试?
- typescript - 从数据对象到简化接口的打字稿
- java - 在 Heroku 上使用 Java 的 NodeJs 应用程序
- python - wxPython 应用程序在启动时显示空白屏幕
- php - htaccess 和 php 目录错误
- javascript - 轮播问题 | 角 6
- java - Spring Boot 自动生成 MySQL 数据库
- python - 尝试从 docker 容器 (Mac) 内部通过 SSH 隧道连接到 MongoDB
- react-native - 在 react-native-datepicker 中将文本左对齐