java 单例 线程阻塞_Java 多线程(四)—— 单例模式

这篇博客介绍线程安全的应用——单例模式。

单例模式

单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。

双重校验锁

实例:

/***@author: ChenHao

* 关于懒汉式的线程安全问题,使用同步机制

* 对于一般的方法内,使用同步方法块,可以考虑使用this

* 对于静态方法而言,使用当前类充当锁。*/

public classTestSingleton {public static voidmain(String[] args) {

System.out.println(MySingle.getInstance());

System.out.println(MySingle.getInstance());

}

}classMySingle{//声明一个私有的静态变量,第一次调用才初始化,避免内存浪费。

private volatile static MySingle instance=null;//让构造器为private私有化,避免外部直接创建对象

privateMySingle(){}public staticMySingle getInstance(){if(null ==instance){//提高效率:如果已经存在对象,则不进行锁等待,直接返回对象,只有当对象为空才会进入锁等待,这里可以在第一个进入锁创建对象后,sleep10秒来放大效果//这里有五个线程等待

synchronized(MySingle.class){//第一次:当一个线程进来后,其他线程都在锁外面//第一个线程创建对象后,释放锁,其他线程得到锁后,如果instance不为null,则不需要创建

if(null ==instance){

instance=newMySingle();try{

Thread.currentThread().sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}returninstance;

}

}

代码分析:多个线程同时创建MySingle类的实例,比如现在有6个线程,第一次同时调用getInstance()静态方法,

线程A获取了锁,其他5个线程都在synchronized(MySingle.class)外面等待,第一个线程创建对象后,释放锁,其他线程得到锁后,如果instance不为null,则不需要创建;

第一个if(null ==instance)作用是提高效率:如果已经存在对象,则不进行锁等待,直接返回对象,只有当对象为空才会进入锁等待,这里可以在第一个进入锁创建对象后,sleep10秒来放大效果,此时已经创建了instance ,但是还没有释放锁,所以新来的线程不需要再等待锁,直接使用已经创建好的instance;

第二个if(null ==instance)判断instance是否已经存在,如果第一个线程已经创建instance,并释放锁,接下来的线程进入后则不需要再创建;

运行结果:输出相同的对象实例

e7b6c8f236ba6530c8c25dcf11811640.png

饿汉

public classSingleton {private static Singleton instance = newSingleton();privateSingleton (){}public staticSingleton getInstance() {returninstance;

}

}

CAS(AtomicReference)实现单例模式

public classSingleton {private static final AtomicReference INSTANCE = new AtomicReference();privateSingleton() {}public staticSingleton getInstance() {for(;;) {

Singleton singleton=INSTANCE.get();if (null !=singleton) {returnsingleton;

}

singleton= newSingleton();if (INSTANCE.compareAndSet(null, singleton)) {returnsingleton;

}

}

}

}

用CAS的好处在于不需要使用传统的锁机制来保证线程安全,CAS是一种基于忙等待的算法,依赖底层硬件的实现,相对于锁它没有线程切换和阻塞的额外消耗,可以支持较大的并行度。

CAS的一个重要缺点在于如果忙等待一直执行不成功(一直在死循环中),会对CPU造成较大的执行开销。而且,这种写法如果有多个线程同时执行singleton = new Singleton();也会比较浪费堆内存。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值