为什么Java中的变量在默认情况下不是易失性的?

2022-09-04 05:00:29

可能类似的问题:

你有没有在Java中使用过volumat关键字?


今天我正在调试我的游戏。它有一个非常困难的线程问题,每隔几分钟就会出现一次,但很难重现。因此,首先,我将关键字添加到我的每个方法中。这不起作用。然后,我将关键字添加到每个字段中。问题似乎只是自行解决。synchronizedvolatile

经过一些实验,我发现负责的字段是一个对象,它跟踪我的游戏的当前状态,可以是正在玩,也可以是忙碌的。忙碌时,游戏会忽略用户输入。我拥有的是一个不断更改变量的线程,而事件线程读取变量。但是,在一个线程更改变量后,另一个线程需要几秒钟才能识别更改,这最终会导致问题。GameStatestatestate

它通过使状态变量来修复。volatile

为什么默认情况下没有Java中的变量,为什么不使用关键字的原因是什么?volatilevolatile


答案 1

长话短说,易失性变量(无论是 Java 还是 C#)永远不会在线程中本地缓存。这不会有太大的影响,除非你正在处理一个多处理器/多核CPU,线程在不同的内核上执行,因为他们会查看相同的缓存。当您将变量声明为易失性时,所有读取和写入都直接来自并直接进入实际的主内存位置;不涉及缓存。这在优化方面有影响,并且不必要地这样做(当大多数变量不需要是易失性的)将造成性能损失(尽管它可能微不足道,也可能不是),以获得相对较小的收益。


答案 2

只有当您尝试编写低级线程安全,无锁代码时,才需要易失性。您的大多数代码可能不应该是线程安全无锁的。根据我的经验,只有在您发现执行锁定的更简单版本由于锁定而导致性能受到重大影响之后,才值得尝试无锁编程。

更令人愉快的选择是 使用其他构建块 ,其中一些是无锁的,但不要像尝试在低级别上自己做的那样弄乱你的头。java.util.concurrent

波动性有其自身的性能成本,没有理由为什么大多数代码应该产生这些成本。