java.单例类懒汉式线程安全问题
来源:互联网 发布:英语短语软件 知乎 编辑:程序博客网 时间:2024/06/05 19:07
鄙渣渣最近在看多线程,在看线程安全问题的时候,不论是学习视频中强调,还是网上搜的单例类、同步、线程安全的面试题中,都有单例类懒汉式线程安全问题。然后又搜了搜,发现有大牛博客上面写了怎么处理懒汉式线程安全问题,却没有说明理由,所以渣渣我结合自己体会写一下。
先小小的介绍一下,单例类是什么
单例类是一种设计思想
简单的基本思想:私有化结构体,通过判断建立的实例是否为空来判断是否能创建对象。使获取对象的途径不是经过结构体,而是通过定义的get函数。
构建单例类的三个基本:
1.只能有一个实例
2.单例类本身必须要建立这个实例
3.要给其他其他对象提供这一实例
单例类有有两个主流格式,饿汉式和懒汉式,实例代码如下:
饿汉式:
class Single { private static final Single f = new Single(); private Single(){}; public static Single get() { return f; } } public class Demo { public static void main(String[] args) { Single f =Single.get(); //因为饿汉式在一开始就建立的对象,所以这里只要通过get方法获取引用变量就可以了 } }
懒汉式:
class Singleton { private Singleton(){} //私有化结构体 private static Singleton single; //建立一个变量缓存创建的实例 public static Singleton get() //用来判断是否建立对象 { if (single == null) { single =new Singleton(); } return single; } } public class person { public static void main(String[] args) { Singleton f = Singleton.get(); //获取对象不通过结构体,而是通过get方法 } }
饿汉式因为在一开始就建立了一个静态对象,所以线程天生安全。
既然饿汉式这么简洁,还线程天生安全,为什么要弄懂懒汉式呢?
因为
面试考的
基本上都是懒汉式
懒汉式为什么线程不安全?
class Singleton { private Singleton(){} private static Singleton single; public static Singleton get() { //1.当有例如A、B、C等多个线程同时进入时 if (single == null) { //--》A //--》B //--》C single =new Singleton(); //2.则会建立多次对象 } return single; } } public class person { public static void main(String[] args) { Singleton f = Singleton.get(); } }
建立多次对象,这是单例类构造中不被允许的。所以存在线程安全问题。
线程安全用同步解决,但如果简单的同步,会使效率变低很多,ex:
class Single { private static Single f = null; private Single(){}; public static Single get() { //每一次线程进入,都要对是否持有锁进行判断,效率偏低 synchronized(Single.class) { if(f==null) f = new Single(); } return f; } } public class Demo { public static void main(String[] args) { Single f =Single.get(); } }
就如代码注释中所写,不论时间先后,每一个线程试图进入时,都要对是否持有锁进行判断,效率偏低。
PS。锁就是锁旗标,也有叫“监视器”的,在我看的视频教学中,讲师将其称之为锁,很形象,就这么叫了。具体请见我的另一片文章 java.关于线程同步 。
所以就有了双重判断的格式用来提高效率:
class Single { private static Single f = null; private Single(){}; //4.后续的C线程进入后 public static Single get() { //4.C线程将在这里被拦截,无法进入 //1.如果有A B两个线程同时进入了 if(f==null) //2.--》A // 2.--》B synchronized(Single.class) { //3.只有一个线程能获取锁 //3.--》A if(f==null) //3.当A线程执行完之后,f就不为空了,当之后的B进入的时候,即使B持有锁,也不会进行对象的建立了 f = new Single(); } return f; } } public class Demo { public static void main(String[] args) { Single f =Single.get(); } }
双重判定使第一个进入的线程执行完之后,两个if判断都将返还false,之后尝试进入的线程在if那一关就会停下,不必每个线程都要判断是否持有锁,在一定程度上提高的效率。
最后附加饿汉式线程安全的几个简单的问题
1.懒汉式和饿汉式的区别:懒汉式存在延迟加载
2.懒汉式的延迟加载有没有问题:有,如果多线程访问,会存在线程的安全问题
3.怎么解决:用同步解决,但用一些同步代码块和同步函数都稍微有些低效,用双重判定的形式,能在一定程度上解决低效问题。
4.加同步的时候,用的锁是哪一个:该类所属的字节码文件对象
可能写的不够形象精确。。。。但渣渣已经尽力了。如果有路过的大神发现哪个地方写的不对,还望指正。
以上。
- java.单例类懒汉式线程安全问题
- java---懒汉式的线程安全问题
- 简单java单例模式 懒汉式、饿汉式以及解决线程安全问题(synchronized)
- 解决单例设计模式中懒汉式线程安全问题
- 解决单例设计模式中懒汉式线程安全问题
- 懒汉式单例模式的线程安全问题
- 多线程编程-线程安全问题浅谈(附懒汉式单例)
- Java 多线程学习笔记(十一) 单例设计模式(延迟加载/懒汉模式)DCL解决线程安全问题
- Java——单例设计模式中懒汉式并发访问的安全问题
- Java线程安全问题
- java线程安全问题笔记
- java线程编程安全问题
- java之线程安全问题
- java线程安全问题
- 关于java线程安全问题
- Java-线程安全问题
- Java 多线程 线程安全问题
- Java-----Servlet线程安全问题
- poj 2031 Building a Space Station
- Notice: Undefined index: submit in D:\.....php on line 2问题
- IOS学习之——欢迎界面
- OSI七层模型
- 一切就这样结束了
- java.单例类懒汉式线程安全问题
- Java中的IO介绍
- 一个图像算法岗的面试总结
- 【Spring实战】—— 15 Spring JDBC模板使用
- mysql set name、set character set区别
- Xcode 6 新建工程运行在 iOS 7 上下有黑边的问题
- eclipse与idea中classpath配置路径不同导致迁移项目时的FileNotFoundException问题
- 动态规划
- [JAVA修炼之路八]-java包Concurrent包-atomic