JAVA单例类线程安全问题
如果一个单例类的变量 只有一个线程A进行修改 其他B C D线程对其进行读取 需要加上Volatile保证其可见性吗?
回答:
一般,最好的单例模式是枚举,这是effective java 中的推荐。
如果枚举没办法满足要求,则推荐延迟初始化占位符这种方式。更加清晰,明了。DCL那种方式容易让人犯错。
public class Singleton { private Singleton(){}
/**
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
* 没有绑定关系,而且只有被调用到时才会装载,从而实现了延迟加载。
*/
private static class SingletonHolder{
/**
* 静态初始化器,由JVM来保证安全" title="线程安全">线程安全
*/
private static Singleton instance = new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}
回答:
需要,必要的话上读写锁
回答:
如果你的目的是读写不冲突,那么最好的解决方法就是加上读写锁,至于加不加Valotile跟这个无关,就算你加上Valotile也只是防止指令重排序而已。
那么什么时候会用到这个Valotile呢?当你对并发要求十分高的时候,什么意思呢?
比如你使用双重检查锁的时候,现在有两个线程,其中一个线程拿到锁开始实例变量的初始化过程。
假设这个初始化过程分为好几步,由于CPU的重排序效果,导致生成实例变量的塞入内存时(其中一步)还没有完全初始化完成(其他几步也参与完成初始化)。
那么此时线程二进入获取实例变量的方法,首先判断实例变量是否为空的返回值将是false,那么它会尝试去内存中拿到这个变量,正如上文所说的的,它拿到的这个变量将是一个中间的状态,因此会出现问题。
为了避免该问题,就需要加上Volotile来防止指令重排序,使初始化过程按步骤进行,内存中的内容一定不是一个中间状态的结果。
但还是那句话,我们真的需要这么极致的防高并发操作么?我想这种情况很难出现。。。所以很多单例的实现中并没有提到这一点。
以上是 JAVA单例类线程安全问题 的全部内容, 来源链接: utcz.com/p/944085.html