单例与线程安全
来源:互联网 发布:复旦大学大数据试验场 编辑:程序博客网 时间:2024/06/05 10:45
说到单例,很容易就想到了饿汉式的单例
public class Singleton {// 实例化private static final Singleton INSTANCE = new Singleton();/** * 构造私有 */private Singleton() {}/** * * @author wiggin * @Description: 获取实例 * @return * */public static Singleton getInstance() {return INSTANCE;}}
这种写法的好处在于它是线程安全的,确保了在多线程情况下,程序内部只有唯一一个实例。
当然他的缺点也是明显的:在类加载的时候,就已经进行实例化,无论之后用不用到。如果该类比较占内存,之后又没用到,就白白浪费了资源。
这个时候就衍生出另外一种单例的写法:实例在需要用的的时候再进行创建,其实也就是为了实现懒加载,这时候就有了下面这种写法
public class Singleton {private static Singleton INSTANCE = null;private Singleton(){}public static Singleton getInstance() {if (INSTANCE == null) {INSTANCE = new Singleton();}return INSTANCE;}}
这种写法确实实现了懒加载,但是却有一个致命的问题:线程不安全,在多线程访问的情况下,有可能实例化多个实例。
那么为了实现线程安全,就有了下面的写法
public class Singleton {private static Singleton INSTANCE = null;private Singleton(){}public static synchronized Singleton getInstance() {if (INSTANCE == null) {INSTANCE = new Singleton();}return INSTANCE;}}
现在是线程安全,但是因为同步范围过大,且大多数情况下并不需要同步,在多线程的情况下,其性能很差。
为了兼顾性能,那就把同步的范围缩小吧,只在实例化的时候加锁,这就有了Double-check写法
public class Singleton {private static Singleton INSTANCE = null;public Singleton() {}public static Singleton getInstance(){if (INSTANCE == null) {synchronized (INSTANCE) {if (INSTANCE == null) {INSTANCE = new Singleton();}}}return INSTANCE;}}
这样子看似完美的解决了之前碰到的问题,但是遗憾的是,这样写依旧是有问题的:jvm指令重排序(正常代码执行顺序应该是1234,但是jvm进行指令重排后,可能是1324),这也使得上面的程序不是绝对的线程安全。此时,就有了下面这种写法
public class Singleton {// volatile关键字private static volatile Singleton INSTANCE = null;public Singleton() {}public static Singleton getInstance(){if (INSTANCE == null) {synchronized (INSTANCE) {if (INSTANCE == null) {INSTANCE = new Singleton();}}}return INSTANCE;}}
引入了volatile关键字,保证了懒加载以及线程安全
阅读全文
0 0
- 单例与线程安全
- 线程安全(单例与多例)
- C++ 单例模式 与线程安全
- C++单例模式与线程安全
- 单例模式与线程安全
- Spring单例与线程安全小结
- Spring单例与线程安全小结
- Spring单例与线程安全小结
- Spring单例模式与线程安全
- Spring单例与线程安全小结
- Spring单例与线程安全小结
- java单例模式与线程安全
- Spring单例与线程安全小结
- 单例模式与线程安全
- Spring单例模式与线程安全
- Spring单例与线程安全小结
- Spring单例与线程安全小结
- Spring单例与线程安全小结
- 第一节总结
- 七牛云-上传策略常用示例
- 219. Contains Duplicate II
- 最小公倍数
- 关闭CPU C State 解决卡屏死机问题
- 单例与线程安全
- GraphQL学习笔记(GraphQL + Spring boot demo) part 2
- 数据库连接池原理和使用
- D3 笔记三:线性比例尺、序数比例尺、domain()、range()
- 求平均成绩
- modelsim 一直loading的解决办法
- 后缀数组详解
- Android短信拦截
- 海选女主角