在Scala中是否可以使用一个本地变量作为Volatile,因为在Java中这是不可能的?
据我所知,Java和Scala中标记为Volatile的字段提供了before关系 在Java中,不可能将方法中的局部变量设置为volatile。然而Scala编译器似乎允许这样的事情,如下面的代码:在Scala中是否可以使用一个本地变量作为Volatile,因为在Java中这是不可能的?,java,multithreading,scala,jvm,Java,Multithreading,Scala,Jvm,据我所知,Java和Scala中标记为Volatile的字段提供了before关系 在Java中,不可能将方法中的局部变量设置为volatile。然而Scala编译器似乎允许这样的事情,如下面的代码: def test: Unit = { @volatile var doNotStop = true } 它的工作方式是否与Java中的工作方式相同?这些代码的语义是什么?在运行时,它在字节码和JVM中的外观如何 在Java中,如果给闭包这样的变量,它可以被另一个线程修改,因此,它必须是fi
def test: Unit = {
@volatile var doNotStop = true
}
它的工作方式是否与Java中的工作方式相同?这些代码的语义是什么?在运行时,它在字节码和JVM中的外观如何
在Java中,如果给闭包这样的变量,它可以被另一个线程修改,因此,它必须是final,对吗 TL;DR:当应用于局部变量时,
@volatile
注释看起来会被忽略,除非该变量可以在闭包内从此局部范围转义
为了确保这一点,我们可以签出与以下代码段对应的字节码
class Foo {
def test: Unit = {
@volatile var doNotStop: Boolean = true
}
}
使用scalac
获得的类文件可以使用javap-c-v-p
进行反编译。以下是测试方法的相关部分:
public void test();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=2, args_size=1
0: iconst_1
1: istore_1
2: return
LocalVariableTable:
Start Length Slot Name Signature
1 1 1 doNotStop Z
...
请注意,没有与任何易失性访问相关的信息
如果我们选择将doNotStop
声明为实例变量,则javap
显示以下字段声明,并带有一个清晰的volatile标志:
private volatile boolean doNotStop;
descriptor: Z
flags: ACC_PRIVATE, ACC_VOLATILE
但是,您对局部变量超出其作用域的担心是完全正确的!让我们试试这个:
class Foo {
def test = {
var doNotStop: Boolean = true
() => doNotStop = false
}
}
使用javap-p
(这次无需查看字节码或标志)为我们提供了以下定义:
public class Foo {
public scala.Function0<scala.runtime.BoxedUnit> test();
public static final void $anonfun$test$1(scala.runtime.BooleanRef);
public Foo();
private static java.lang.Object $deserializeLambda$(java.lang.invoke.SerializedLambda);
}
该类基本保持不变,但$anonfun$test$1
现在需要volatileboleanref
。猜猜它的内部布尔值是如何实现的:
volatile public boolean elem;
这里的语义非常清楚:您的非局部Boolean
变量在运行时表示为BooleanRef
实例的字段。注释可能会将此字段标记为volatile
。好了,@volatile
毕竟在那里很有用
回答你的第二个问题:Java的闭包只关闭那些“实际上是最终的”值,这将不允许这种模式,doNotStop
的值在闭包中发生变化。当然,您可以使用与此处相同的方法实现它,使用对(Volatile)的“有效最终”引用BooleanRef
的elem
可以通过闭包自由修改。在Java中不可能的原因是一个Java线程无法从不同的线程访问局部变量。我不知道Scala,但我很确定,即使你能做到,这也不是一个好主意。你可以使用scalac
编译代码,然后使用javap
反编译回来。我会让你看一看发生了什么事。
volatile public boolean elem;