同步代码块解决单例懒汉式线程安全问题

面试复现

面试官:懒汉式和饿汉式有什么不同?

你:饿汉式特点在于有实例的延迟加载

面试官:懒汉式延迟加载有没有什么问题?

你:懒汉式如果多线程访问时有线程安全问题,可以使用同步的方式来解决,同步代码块和同步代码函数都可以,但是同步代码函数稍微有点低效率,用同步代码块的双重判断的形式可以解决这个问题

面试官:加同步的时候使用的锁是哪一个?

你:该类所属的字节码文件对象

面试官:好了你对薪资有什么看法 (ヾ(≧▽≦*)o 内心OS)

 哈哈哈以上纯属个人脑补,但是这么一个简单的知识点就有N多的考点,还是比较值的注意一下的,我们简单实现下以上对话的代码

代码实现

饿汉式做对比

package cn.icnfox.Java;

public class Single
{
	private static final Single s = new Single();
	private Single(){}
	public static Single getInstance()
	{
		return s;
	}
}

懒汉式

package cn.icnfox.Java;

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


	public static  Single getInstance()
	{

	 if(s==null)
		s = new Single();
		 return s;
	}
}

 我们现在思考这么一种情况:

  1. 多线程并发访问getInstance(),A线程进行if判断后进入阻塞状态,此时B线程进行if判断后也进入阻塞状态
  2. A线程可运行后执行了一次s = new Single(); B线程可运行后又执行了一次s = new Single();

 此时就出现了一个问题,没有办法保证单例懒汉式的对象唯一性,懒汉式在多线程访问时产会有安全隐患,我们使用同步代码函数可以解决这个问题

package cn.icnfox.Java;

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


	public static synchronized Single getInstance()
	{

	 if(s==null)
		s = new Single();
		 return s;
	}
}

 但是由此又产生了一个问题,就是多线程访问的时候,每个线程想获取实例都需要判断一次锁,所以加同步会比较低效,最终我们使用同步代码块并且引入双重判断来解决这个问题.

package cn.icnfox.Java;

public 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;
	}
}

本人个人网站: https://www.icnfox.cn 欢迎来访
有任何问题可以在个人网站的评论区留言,看到就会第一时间回复 啾咪ヾ(≧▽≦*)o

你可能感兴趣的:(Java)