【发布时间】:2011-03-03 13:34:03
【问题描述】:
我偶尔会使用volatile 实例变量,因为我有两个线程读取/写入它并且不希望获取锁的开销(或潜在的死锁风险);例如,一个计时器线程定期更新一个 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 位读取将是原子的,曾经使用 volatile long 有什么意义吗? (即 64 位)。
警告:请不要回复说使用volatile 而不是synchronized 是预优化的情况;我很清楚如何/何时使用synchronized,但在某些情况下volatile 更可取。例如,在定义用于单线程应用程序的 Spring bean 时,我倾向于使用 volatile 实例变量,因为不能保证 Spring 上下文会在主线程中初始化每个 bean 的属性。
【问题讨论】:
-
注意,
++不是原子操作。我建议改用java.util.concurrent.atomic.AtomicInteger。 -
谢谢汤姆 - 这只是一个简单的例子。
-
顺便说一句,你不需要在 Spring 中使用
volatile。 Spring 在初始化您的类时使用锁,并且发生前的关系将为您处理排序
标签: java multithreading concurrency volatile