前言:
现时各位老铁们对“单例模式 锁”大致比较珍视,你们都需要学习一些“单例模式 锁”的相关内容。那么小编也在网摘上搜集了一些有关“单例模式 锁””的相关资讯,希望大家能喜欢,咱们一起来了解一下吧!单例模式(singleton)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。单例模式是创建模式。单例模式在现实生活中应用也非常广泛,例如。公司的CEO、部门经理等。J2EE标准中的ServletContext、ServletContextConfig等,spring框架应用中的ApplicationContext,数据库的连接池等也是单例模式。
饿汉式单例模式
饿汉式单例模式在类加载的时候就立即初始化,并且创建单例对象。她绝对的线程安全,在线程还没有出现以前就已经实例化了,不可能存在访问安全问题
标准代码:
另外一种写法,利用静态代码块机制:
这两种写法都非常简单,也非常好理解,饿汉式单例模式适用于单例对象较少的情况。这样写可以保证线程的绝对安全、执行效率比较高。但是它的确定也比较明显,就是所有对象类加载的时候就实例化。这样一来,如果系统中有大批量的单例对象存在,那系统初始化时就会导致大量的内存浪费。也就是说,不管对象用于不用都占着空间,浪费了内存,有可能“占着茅坑不拉屎”。
懒汉式单例模式
为了解决饿汉式单例可能带来的内存浪费问题,于是就出现了懒汉式单例的写法,懒汉式单例模式的特点,单例对象要在被使用时才会初始化,
懒汉式的简单实现代码:
但是这样写又带来了一个新的问题,如果在多线程环境下,就会出现线程安全问题。
编写线程类 ExectorThread:
客户端代码测试如下:
运行结果如下图所示:
果然,上面的代码有一定的概率出现两种不同结果,这意味着上面的单例存在线程安全隐患。那么我们如何通过优化代码,使得懒汉式单例模式在多线程环境下安全呢?来看下面的代码,通过给getInstance() 加上synchronized关键字,使这个方法变成线程同步方法
再次测试,运行结果如下:
线程安全的问题解决了。但是,用synchronized加锁时,在线程数量比较多的情况下,如果CPU分配压力上升,则会导致大批线程阻塞,从而导致程序性能大幅下降。为了避免这种情况的发生,我们使用双重检查锁的单例模式:
此时,阻塞并不是基于整个LazyDoubleSingleton类的阻塞,而是在getInstance方法内部的阻塞,只要逻辑不是太复杂,对于调用者是感知不到的。
但是,用到synchronized关键字总归是要上锁,对程序性能还是存在一定影响的。为了更好的解决,我们采用静态内部类的方式:
这种方式兼顾了饿汉式单例模式的内存浪费问题和synchronized的性能问题。内部类一定是要在方法电泳之前初始化,巧妙的避免了线程安全问题。这种方式主要是用到类的加载机制,比较简单就不调试了。
标签: #单例模式 锁