单例模式
单例模式:保证一个类仅有一个实例,并提供一个访问它全局访问点
比如下面的类就是一个单例模式
普通的单例模式
1 | class Singleton { |
以上的类就是不允许你在外部直接 new Singleton,每次获取这个类实例只能通过 Singleton.getInstance() 这种方式来获取,而这个方案保证了只实例化一次类实例
多线程的单例模式
上面的一个模式仅仅对于单线程有用,在多线程的世界里或者是在高并发程序中,这种方法往往是无效的,为什么呢?
因为单线程是从上往下执行的,而多线程是同时一起执行的,所以,里面的 new Singletone() 这个方法在高并发的情况下,肯定会存在多个线程都走到这一步,也就造成了实例化了多次 instance,这显然和单例模式冲突的
我们可以通过加锁来解决这个问题
1 | class Singleton { |
对比单线程的代码,我们增加多了一把锁来完成
疑问1:为什么不直接 lock(instance) 呢?
因为在加锁的时候还不知道 instance 到底有没有被实例化
疑问2:前面已经有判断instance == null 了,为什么下面还要加上 if (instance == null) 呢?
这是因为当两个线程同时到达第一个判断的时候,必然有一方是先抢占到锁的,那么另一方就只能等待他释放锁(就好像只有一间洗手间,两个人同时进来,那当然只能有一个先进去,而另外一个在里面等待),当第一个线程进去以后,发现没有实例化,那么实例化之后释放锁就 return 了,而第二个线程进来后通过判断发现已经 instance 了,所以就不重复实例化了,也直接 return 了。所以,如果没有 if 判断的话,第二个线程进来以后仍然会继续实例化,这也就和单例模式冲突了。
参考:《大话设计模式》的单例模式
install_url
to use ShareThis. Please set it in _config.yml
.