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

 更新时间:2016年12月27日 11:23:57   投稿:jingxian  
下面小编就为大家带来一篇完美解决单例设计模式中懒汉式线程安全的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

首先写个单例:

public class SingleDemo { 
  private static SingleDemo s = null; 
  private SingleDemo(){} 
  public static SingleDemo getInstance(){ 
    if(s == null){ 
      s = new SingleDemo(); 
    } 
    return s; 
  } 
} 

写个测试类:

public class ThreadDemo3 { 
   
  public static void main(String[] args) { 
    SingleDemo s1 = SingleDemo.getInstance(); 
    SingleDemo s2 = SingleDemo.getInstance(); 
    System.out.println(s2 == s2); 
  } 
} 

运行结果一直都是true,说明单线程下是没问题的,下面写个多线程来访问单例

public class ThreadTest implements Runnable { 
  //存放单例对象,使用Set是为了不存放重复元素 
  public Set<SingleDemo> singles = new HashSet<SingleDemo>(); 
  @Override 
  public void run() { 
    //获取单例 
    SingleDemo s = SingleDemo.getInstance(); 
    //添加单例 
    singles.add(s); 
  } 
} 

使用多线程并发访问单例:

public class ThreadDemo3 { 
   
  public static void main(String[] args) { 
//   SingleDemo s1 = SingleDemo.getInstance(); 
//   SingleDemo s2 = SingleDemo.getInstance(); 
//   System.out.println(s2 == s2); 
    ThreadTest t = new ThreadTest(); 
    new Thread(t).start(); 
    new Thread(t).start(); 
    new Thread(t).start(); 
    new Thread(t).start(); 
    new Thread(t).start(); 
    new Thread(t).start(); 
    new Thread(t).start(); 
    new Thread(t).start(); 
    System.out.println(t.singles); 
  } 
} 


运行结果如下:
[com.persagy.thread.SingleDemo@1bc4459, com.persagy.thread.SingleDemo@150bd4d]

[com.persagy.thread.SingleDemo@12b6651]

说明有线程并发访问安全问题,获取的不一定都是同一个实例

如何解决线程安全问题呢?

当然使用同步锁机制了啊

下面改进单例:

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

加入同步函数后线程安全问题解决了

运行多次都是获取同一个实例,不会出现2个实例的情况了

[com.persagy.thread.SingleDemo@12b6651]

但是在多线程并发访问的情况下,每个线程每次获取实例都要判断下锁,效率比较低,为了提高效率,我加入了双重判断的方法,解决了效率的问题

代码如下:

public class SingleDemo {
	private static SingleDemo s = null;
	private SingleDemo(){}
	public static SingleDemo getInstance(){
		/*如果第一个线程获取到了单例的实例对象,
		 * 后面的线程再获取实例的时候不需要进入同步代码块中了*/
		if(s == null){
			//同步代码块用的锁是单例的字节码文件对象,且只能用这个锁
			synchronized(SingleDemo.class){
				if(s == null){
					s = new SingleDemo();
				}
			}
		}
		return s;
	}
}

用这种方式解决了懒汉式的线程安全问题,也提高了效率,但是在实际开发中还是用饿汉式的比较多,毕竟这个代码比较多,比较繁琐。

以上就是小编为大家带来的完美解决单例设计模式中懒汉式线程安全的问题全部内容了,希望大家多多支持脚本之家~

相关文章

  • Redisson可重入锁解锁逻辑详细讲解

    Redisson可重入锁解锁逻辑详细讲解

    Redisson开源框架是一个Redis的分布式锁的现成实现方案,是Redis的java实现的客户端。通过Netty支持非阻塞I/O。Redisson实现了分布式锁的自动续期机制、锁的互斥自等待机制、锁的可重入加锁与释放锁的机制
    2023-02-02
  • Spring Boot利用Thymeleaf发送Email的方法教程

    Spring Boot利用Thymeleaf发送Email的方法教程

    spring Boot默认就是使用thymeleaf模板引擎的,下面这篇文章主要给大家介绍了关于在Spring Boot中利用Thymeleaf发送Email的方法教程,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-08-08
  • JUnit5中的参数化测试实现

    JUnit5中的参数化测试实现

    参数化测试使得我们可以使用不同的参数运行同一个测试方法,从而减少我们编写测试用例的工作量,本文主要介绍了JUnit5中的参数化测试实现,感兴趣的可以了解一下
    2023-05-05
  • 深入Spring Boot实现对Fat Jar jsp的支持

    深入Spring Boot实现对Fat Jar jsp的支持

    这篇文章主要介绍了深入Spring Boot实现对Fat Jar jsp的支持,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • Maven下 mybatis-generator使用

    Maven下 mybatis-generator使用

    这篇文章主要介绍了Maven下 mybatis-generator使用 ,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-09-09
  • Java 客户端操作 FastDFS 实现文件上传下载替换删除功能

    Java 客户端操作 FastDFS 实现文件上传下载替换删除功能

    这篇文章主要介绍了Java 客户端操作 FastDFS 实现文件上传下载替换删除功能,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • java面向对象的三大特性之一继承用法实例分析

    java面向对象的三大特性之一继承用法实例分析

    这篇文章主要介绍了java面向对象的三大特性之一继承用法,结合实例形式分析了java面向对象程序设计中继承的基本原理与具体使用方法,需要的朋友可以参考下
    2019-11-11
  • Springboot整合Mybatis传值的常用方式总结

    Springboot整合Mybatis传值的常用方式总结

    今天给大家带来的是关于Springboot的相关知识,文章围绕着Springboot整合Mybatis传值的常用方式展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • 简单了解JAVA变量类型及代码实例

    简单了解JAVA变量类型及代码实例

    这篇文章主要介绍了简单了解JAVA变量类型及代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • java控制Pdf自动打印的小例子

    java控制Pdf自动打印的小例子

    java控制Pdf自动打印的小例子,需要的朋友可以参考一下
    2013-04-04

最新评论