使用 volatile long 有什么意义吗?
当我有两个线程读取/写入它并且不希望取出锁的开销(或潜在的死锁风险)时,我偶尔会使用 易失性实例变量;例如,一个计时器线程定期更新一个 int ID,该 ID 在某个类上作为 getter 公开:
public class MyClass {
private volatile int id;
public MyClass() {
ScheduledExecutorService execService = Executors.newScheduledThreadPool(1);
execService.scheduleAtFixedRate(new Runnable() {
public void run() {
++id;
}
}, 0L, 30L, TimeUnit.SECONDS);
}
public int getId() {
return id;
}
}
我的问题:鉴于 JLS 仅保证 32 位读取将是原子的,是否有任何一点永远使用易失性长? (即 64 位)。
警告:请不要回复说使用 volatile
而不是 synchronized
是预优化的情况;我很清楚如何/何时使用synchronized
,但在某些情况下volatile
更可取。例如,当定义在单线程应用程序中使用的 Spring bean 时,我倾向于使用易失性实例变量,因为不能保证 Spring 上下文会在主线程中初始化每个 bean 的属性。
I occasionally use a volatile
instance variable in cases where I have two threads reading from / writing to it and don't want the overhead (or potential deadlock risk) of taking out a lock; for example a timer thread periodically updating an int ID that is exposed as a getter on some class:
public class MyClass {
private volatile int id;
public MyClass() {
ScheduledExecutorService execService = Executors.newScheduledThreadPool(1);
execService.scheduleAtFixedRate(new Runnable() {
public void run() {
++id;
}
}, 0L, 30L, TimeUnit.SECONDS);
}
public int getId() {
return id;
}
}
My question: Given that the JLS only guarantees that 32-bit reads will be atomic is there any point in ever using a volatile long? (i.e. 64-bit).
Caveat: Please do not reply saying that using volatile
over synchronized
is a case of pre-optimisation; I am well aware of how / when to use synchronized
but there are cases where volatile
is preferable. For example, when defining a Spring bean for use in a single-threaded application I tend to favour volatile
instance variables, as there is no guarantee that the Spring context will initialise each bean's properties in the main thread.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不确定我是否正确理解您的问题,但是 JLS 8.3.1.4。易失性字段指出:
也许更重要的是, JLS 17.7 非-double和long的原子处理:
也就是说,“整个”变量受到 volatile 修饰符的保护,而不仅仅是两个部分。这让我忍不住想说,在
long
中使用 volatile 比在int
中使用更重要,因为甚至都不是对于非易失性长整型/双精度,读取是原子的。Not sure if I understand your question correctly, but the JLS 8.3.1.4. volatile Fields states:
and, perhaps more importantly, JLS 17.7 Non-atomic Treatment of double and long :
That is, the "entire" variable is protected by the volatile modifier, not just the two parts. This tempts me to claim that it's even more important to use volatile for
long
s than it is forint
s since not even a read is atomic for non-volatile longs/doubles.这可以通过示例
,这种情况永远不会发生在受易失性代码
输出
请注意,这只发生在我在 32 位 VM 上运行时,在 64 位 VM 上我在几分钟内无法收到任何错误。
This can be demonstrated by example
Code
Output
Note this only happens for me when running on a 32 bit VM, on 64 bit VM I couldn't get a single error in several minutes.
“易失性”有多种用途:
while (l != 0) {}
。还有更多吗?
"volatile" serves multiple purposes:
while (l != 0) {}
.Is there more?