关于这个问题有几个问题,但大多数都围绕这个问题,因为这不是问题的意图.
如果我班上有静态易失性:
- private static volatile MyObj obj = null;
在下面的方法中我做:
- public MyObj getMyObj() {
- if (obj == null) {
- obj = new MyObj();// costly initialisation
- }
- return obj;
- }
我需要同步以确保只有一个线程写入该字段,或者任何写入是否会立即显示给评估obj == null条件的其他线程?
换句话说:volatile是否会让你不得不同步访问静态变量上的写入?
解决方法
你肯定需要某种锁定来确保只有一个线程写入字段.无论波动性如何,两个线程都可以“看到”obj为null,然后两个线程都开始使用当前代码进行初始化.
就个人而言,我会选择以下三个选项之一:
>在类加载时初始化(知道这将是懒惰的,但不像在第一次调用getMyObj之前那样懒惰):
- private static final MyObj obj = new MyObj();
>使用无条件锁定:
- private static MyObj obj;
- private static final Object objLock = new Object();
- public static MyObj getMyObj() {
- synchronized(objLock) {
- if (obj == null) {
- obj = new MyObj();
- }
- return obj;
- }
- }
>使用嵌套类进行懒惰:
- public static MyObj getMyObj() {
- return MyObjHolder.obj;
- }
- private static class MyObjHolder {
- static final MyObj obj = new MyObj();
- }