懒汉式单例模式的线程安全问题

原创 2015年07月11日 09:24:58

所谓线程不安全实际上就是一段代码在同一时间被两个线程同时执行,导致运行结果与单个线程运行结果不相同。如下面提到的if 判断语句。
新建一个单例模式类和一个多线程测试类

<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>




版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

单例设计模式详解一:不安全的懒汉式(多线程环境验证)

单例设计模式详解一:不安全的懒汉式(多线程环境验证)单例设计模式详解一不安全的懒汉式多线程环境验证 写在前面的话 饿汉式 懒汉式 验证在多线程环境下懒汉式单例写法的不安全之处 写在前面的话前言:虽然工...

线程简介--单利模式饿汉式和懒汉式

1/创建线程:类继承Thread类复写Runnable的run()方法。start()作用:调用run方法、开启线程。只有调用Strat()方法才能开启线程。 2/线程的的状态:创建、运行、阻塞、死...

解决单例设计模式中懒汉式线程安全问题

---------------------------------------- android培训、 java培训 、期待与您交流! ------------------------------...

单例模式中懒汉模式的非线程安全问题的解决方法

单例模式中懒汉模式的非线程安全问题的解决方法    单例模式中有饿汉模式和懒汉模式两种。饿汉模式也叫立即加载 ,即在get之前就已经创建实例instance; package singleton1;...

设计模式(一)--深入单例模式(涉及线程安全问题)

这又是一个新的系列啦,探究各大设计模式在开发中必须注意思考的一些问题,以及它们的多向使用。文章结构:(1)单例模式概念以及优缺点(2)各式各样的单例及其线程安全问题。(3)使用推荐。...

单例设计模模式——懒汉式为什么线程不安全

单例设计模式分为两种饿汉式,懒汉式无论哪一种,思想就三步,0;就一个实例,则不能被实例化,所有构造函数私有的1:提供一个实例2:提供一个供外部访问的方法 懒汉式线程不安全,那为什么不安全呢?看代码!...
  • L_ILove
  • L_ILove
  • 2017年01月09日 21:39
  • 1794

单例模式中,饿汉式和懒汉式有什么区别?各适合用在哪里?为什么说推荐用饿汉模式?

饿汉式:         public class Singleton{             private static Singleton singleton = new Singleto...

高并发下线程安全的单例模式(最全最经典)

在所有的设计模式中,单例模式是我们在项目开发中最为常见的设计模式之一,而单例模式有很多种实现方式,你是否都了解呢?高并发下如何保证单例模式的线程安全性呢?如何保证序列化后的单例对象在反序列化后任然是单...
  • cselmu9
  • cselmu9
  • 2016年05月11日 00:32
  • 50089

解决单例设计模式中懒汉式线程安全问题

解决单例设计模式中懒汉式线程安全问题

多线程 - 单例设计模式(懒汉式)

//饿汉式: class Single { private static final Single s = new Single();//先初始化函数,加上final后更加严谨,确认唯一的变量 p...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:懒汉式单例模式的线程安全问题
举报原因:
原因补充:

(最多只允许输入30个字)