multithreading - Local variable can be mutated from child threads in Scala
问题描述
Today I was trying to learn about memory management in the JVM and I came across the following question: can I mutate a local variable from two threads spawned within the same function?
In Java, if you try something like this the code will not compile, yielding an error with message "local variables referenced from an inner class must be final or effectively final"
public class MyClass {
static void f() throws Exception {
int x = 0;
Thread t1 = new Thread(new Runnable() {
public void run() {
for(int i = 0; i < 1000; i++) {
x = x + 1;
}
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
for(int i = 0; i < 1000; i++) {
x = x - 1;
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(x);
}
public static void main(String args[]) throws Exception {
for(int i = 0; i < 20; i++) {
f();
}
}
}
However the equivalent code in Scala does compile and run without problem (despite maybe race conditions):
def f(): Unit = {
var x = 0
val t1 = new Thread(new Runnable {
override def run(): Unit =
(1 to 1000).foreach(_ => {x = x + 1})
})
t1.start()
val t2 = new Thread(new Runnable {
override def run(): Unit =
(1 to 1000).foreach(_ => {x = x - 1})
})
t2.start()
t1.join()
t2.join()
println(x)
}
(1 to 20).foreach(_ => f())
Why is the behavior different in each case?
解决方案
In Scala lambdas, and by extension anonymous classes, can capture local variables. The scala.runtime
package contains some extra classes for that purpose. They effectively lift the local variable into an instance variable of another class whose instances can be shared: https://github.com/scala/scala/blob/v2.13.3/src/library/scala/runtime/ObjectRef.java
推荐阅读
- assembly - 在 x86-64 中,pcmpestri 指令在 RAX 和 RDX 中以字符为单位还是以字节为单位获取其长度参数?
- python - 在 GAE + python + Flask 中检索 URL 路径时出错
- python - dateparser 是如何得到这个结果的?
- javascript - 如何获得一系列反应 Discord JS
- assembly - 如何在 Pep9 程序集中编写 if 语句?
- hadoop - HIVE:我不能放弃视图
- r - 夸克在 R 中使用 LM 模型生成拟合值
- ios - 显示从 datePicker 中选择的值到 alertController 内的 textField
- selenium - Chromedriver 版本在 chromium 网站和 maven 存储库中的标记不同。chromedriver应该考虑哪一个?
- java - GRPC Async + Blocking Stub Java