懒汉式单例模式的线程安全问题
2015-07-11 09:24
316 查看
所谓线程不安全实际上就是一段代码在同一时间被两个线程同时执行,导致运行结果与单个线程运行结果不相同。如下面提到的if 判断语句。
新建一个单例模式类和一个多线程测试类
说明有线程并发访问安全问题,获取的不是同一个实例
解决方案(1):使用同步锁机制,最简单的是在getInstance()方法上加synchronized关键字
代码如下:
解决方案(2):改恶汉式单例为懒汉式单例
新建一个单例模式类和一个多线程测试类
<span style="font-size:14px;">public class Test24 implements Runnable { public void run() { System.out.println(TestSingleton.getInstance()); } public static void main(String[] args) { Test24 test1 = new Test24(); Test24 test2 = new Test24(); Thread thread1 = new Thread(test1); Thread thread2 = new Thread(test2); thread1.start(); thread2.start(); } } class TestSingleton { private static TestSingleton testSingleton; private TestSingleton() { System.out.println("建新的对象"); } public static TestSingleton getInstance() { if (testSingleton == null) { testSingleton = new TestSingleton(); } return testSingleton; } }</span>执行后发现会产生两个新的对象。控制台打印:
<span style="font-size:14px;">建新的对象 建新的对象 com.TestSingleton@328d5485 com.TestSingleton@5ca801b0</span>
说明有线程并发访问安全问题,获取的不是同一个实例
解决方案(1):使用同步锁机制,最简单的是在getInstance()方法上加synchronized关键字
<span style="font-size:14px;">public static synchronized TestSingleton getInstance() { if (testSingleton == null) { testSingleton = new TestSingleton(); } return testSingleton; }</span>对于这种方式,有人觉得在多并发的情况下,每次获取实例都要判断锁,效率比较低下,所以就有人想出了这样的办法,双重判断实例,这种大大减少判断同步锁的次数了。所以实际使用中可以推广。
代码如下:
<span style="font-size:14px;"> public static TestSingleton getInstance() { /* * 如果第一个线程获取到了单例的实例对象, 后面的线程再获取实例的时候不需要进入同步代码块中了 */ if (testSingleton == null) { // 同步代码块用的锁是单例的字节码文件对象,且只能用这个锁 synchronized (TestSingleton.class) { if (testSingleton == null) { testSingleton = new TestSingleton(); } } } return testSingleton; }</span>
解决方案(2):改恶汉式单例为懒汉式单例
<span style="font-size:14px;">class TestSingleton { private static TestSingleton testSingleton=new TestSingleton(); private TestSingleton() { System.out.println("建新的对象"); } public static TestSingleton getInstance() { return testSingleton; } }</span>
相关文章推荐
- 日经社説 20150711 法改正を機に企業は攻めの知財戦略を
- js 时间相关函数
- PHP编码风格(转)
- python __file__ 与argv[0]
- 页面回到顶部的三种实现(锚标记,js)
- ORACLE ORA-00942:表或视图不存在
- 协方差的意义和计算公式
- 编程中遇到的问题小结
- 抽象(继承)
- iOS中UILabel的用法(三 )
- 笔试题&面试题:CW输出矩阵
- ExtJS学习笔记:定义extjs类别
- 观察者模式
- NI 更新还是获得了USB端口的权限
- 日经社説 20150711 転職しやすい社会へ踏み出せ
- iOS 9公测开启 智能预测/省电模式亮相
- LeetCode Implement Stack using Queues
- eclipse中项目文件变更位置后的浏览器读取地址的变化
- Java - 判断元音辅音
- sql 范式