我偶尔使用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
代替。 - Tom Hawtin - tacklinevolatile
。Spring在初始化你的类时会使用锁,并且 happens-before关系会为你处理好顺序问题。 - oxbow_lakes