单例设计模式II (懒汉式)

本文详细阐述了Java单例设计模式中的懒汉式实现方式及其潜在问题,通过实例展示了如何引入同步锁解决线程安全问题,并介绍了优化策略以提高代码运行效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单例设计模式I (饿汉式)在开发中比较常见。而另一种写法,即懒汉式主要用于面试考试。


但因为感觉比较有趣,所以单独列出做个记录。


懒汉式:对象延迟加载。

思路:类存在时内部没有对象,只有当调用方法时才会在类中建立对象(比喻相当形象啊……到底是有多懒= =|||)。


特点:

对象延迟加载;

容易存在安全隐患;


先来最终解决方案的看代码:

class Single
{
	private static Single s= null;
	
	private Single(){}

	public static Single getInstance()
	{
		if(s== null)
		{
			synchronized(Single.class)
			{
				if(s== null)
				{
					s= new Single();
				}
			} 
		}
		return s;	
	}
}


—————————————————(我是现在很饿的分割线)——————————————————


然后这个是基本懒汉式的代码:

class Single
{
	private static Single s= null;
	
	private Single(){}

	public static Single getInstance()
	{
		if(s== null)
			s= new Single();
		
		return s;	
	}
}



主要问题出在 getInstance( ) 方法中;


因为CPU的一个核心在同一时刻只能处理一个任务,为了高效处理多个任务,它会在极小的时间单位里随机进行不同任务的之间的切换。


现在假设程序A调用了 getInstance( ) 方法,并运行到了这条语句:

if(s== null)
此刻CPU却切换到了其他任务,于是程序A就挂在了此处。

于此同时,程序B也调用了 getInstance( ) 方法,进入并执行了语句:

if(s== null)
	s= new Single();
因为此前程序A在创建对象之前由于CPU切换而挂停,所以此时程序B判断 s 的值为空是成立的,因此可以创立对象。


接着,CPU切换回来,程序A继续读下面的语句,注意此处A已经判断过 s 的值为空,所以依然可以创立对象。

于此,对象在类中的唯一性就已经被打破了。


解决方案为同步锁(其实并没有学到这里,只是老师单独讲解了一下并提到了这个,名称也许不正式)

public static Single synchronized getInstance()
	{
		if(s== null)
			s= new Single();
				
		return s;	
	}


在方法前加上同步锁 synchronized 可以使调用者在进入前进行判断,如果该方法没有人调用,就进入。否则不调用。

这样基本解决了对象在类中的唯一性问题,但却托慢了代码的运行效率。


因为每次调用前都会对同步锁进行判断,多次调用多次判断十分低效。

优化思想为双重判断,代码如下:

public static Single getInstance()
	{
		if(s== null)
		{
			synchronized(Single.class)
			{
				if(s== null)
				{
					s= new Single();
				}
			} 
		}
		return s;	
	}

重新使用上面的例子:

首先程序A调用 getInstance( ) 方法,判断 s 值为空,进入然后对锁进行判断,锁内没有程序,进入。

如果此时CPU进行了切换导致程序A挂停,当程序 B 调用方法时,再进行判断同步锁时,则发现锁内有程序进入,即停止调用。

如果锁告知内部没有程序,即直接进入进行对象创建。

于此,不需要每次调用 getInstance( ) 方法时都判断一次同步锁,提高了代码的运行效率。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值