Singleton和Double-Checked Locking设计模式,分别指的是单例模式和双重检查锁模式,它们都可以用于确保某个类只有一个对象实例化。

两个模式的区别在于:Singleton模式用在单线程应用程序中,而Double-Checked Locking模式用于多线程模式。

一、Singleton模式

UML图:

代码:

  1. package bupt.xujinliang.singletonpattern;
  2. /**
  3. *
  4. * @author jin
  5. *
  6. */
  7. public class SingletonExample {
  8. public static void main(String[] args) {
  9. Printer printer1 = Printer.getInstance();
  10. Printer printer2 = Printer.getInstance();
  11. if(printer1 == printer2) {
  12. System.out.println("printer2 point to the same address with printer1");
  13. } else {
  14. System.out.println("printer2 point to different address with printer1");
  15. }
  16. }
  17. }
  18. class Printer {
  19. private static Printer instance;
  20. public Printer() {
  21. System.out.println("Printer Constructor");
  22. }
  23. public static Printer getInstance() {
  24. if(null == instance)
  25. instance = new Printer();
  26. return instance;
  27. }
  28. }

运行结果:

2.Double-Checked Locking模式

Double Check Locking模式是singleton的多线程版本,必须使用锁来锁定临界区,当多个线程存在访问临界区的意图时,保证了临界区只被访问一次。
首先介绍其在C/C++环境下的实现过程:
代码1:
  1. Printer* get_instance(void)
  2. {
  3. lock();
  4. if( instance == 0) {
  5. instance = new Printer;
  6. }
  7. unlock();
  8. return instance;
  9. }

上述代码存在的问题是:无论是否已经初始化都要加锁,增加了负荷,已经没有所谓的并发性能了。

代码2:
  1. Printer* get_instance(void)
  2. {
  3. if( instance == 0){
  4. lock();
  5. instance = new Printer;
  6. unlock();
  7. }
  8. return instance;
  9. }

上述代码存在的问题是:不能保证临界区只初始化一次,没能实现singleton的基本功能。

代码3:
  1. Printer* get_instance(void)
  2. {
  3. if( instance == 0){
  4. lock();
  5. if( instance == 0 )
  6. instance = new Printer;
  7. unlock();
  8. }
  9. return instance;
  10. }

这是比较完善的Double-Checked Locking模式实现的代码。

为什么叫做Double-Checked Locking呢?请看上述代码3,可以看到在加锁前后都对instance变量进行了检查,故谓之Double-Checked Locking。
那么在Java中的实现与在C/C++中不同吗?是的。
下面的的Java代码是不能够实现Double-Checked Locking模式的:
  1. class Printer {
  2. private static Printer resource ;
  3. public static Printer getInstance(){
  4. if(resource == null ){
  5. synchronized (DoubleCheckedLockingExample.class) {
  6. if(resource  == null ){
  7. resource  = new Printer() ;
  8. }
  9. }
  10. }
  11. return resource ;
  12. }
  13. private Printer(){}
  14. }

上面程序真正的问题是没有同步的情况下读取共享变量resource,并发的情况下对象的状态值有可能是过期无效的。要解决这个问题也很简单,把resource声明为volatile类型。volatile有什么作用?引用《java并发编程实战》的解析:

  1. 当一个域声明为volatile类型后,编译器与运行时会监视这个变量:它是共享的,而且对它的操作不会与其他的内存操作一起被重排序。volatile变量不会缓存在寄存器或缓存在对其他处理器隐藏的地方。所以,读一个volatile类型的变量时,总会返回由某一线程所写入的最新值。

读取volatile变量比读取非volatile变量的性能几乎没有差别,不过需要注意的是volatile只能保证内存可见性,并不能保证原子性。

现给出Java在多线程下实现单个实例化对象的方法:
  1. class Printer {
  2. private static class Instance {
  3. static final Printer instance = new Printer();
  4. }
  5. private static Printer resource ;
  6. public static Printer getInstance(){
  7. return Instance.instance;
  8. }
  9. private Printer(){}
  10. }

上述方法之所以有效,是因为内部类(Instance)将只被装载一次,所以只会创建一个对象。

[zt]Singleton和Double-Checked Locking设计模式—UML图及代码实现的更多相关文章

  1. Java中的双重检查锁(double checked locking)

    最初的代码 在最近的项目中,写出了这样的一段代码 private static SomeClass instance; public SomeClass getInstance() { if (nul ...

  2. Double Checked Locking 模式

    转自:http://blog.csdn.net/wwsoon/article/details/1485886 之前在使用Double Check Locking 模式时,发现自己还是不太理解.于是写个 ...

  3. 设计模式-UML图简单介绍

    直接上法宝: 1.类(Class)     类图分三层:     第一层显示类的名称,如果是抽象类,则就用斜体显示.     第二层是类的特性,通常就是字段和属性.     第三层是类的操作,通常是方 ...

  4. 设计模式UML图

    1.简单工厂模式 2.工厂模式 工厂模式与简单工厂模式的不同在于,每个操作类都有自己的工厂,而且把逻辑判断交给了客户端,而简单工厂的逻辑判断在工厂类里边,当增加新的操作类时,简单工厂需要修改工厂类,而 ...

  5. 【转】23种设计模式UML图

    原文:http://blog.csdn.net/bwwlpnn/article/details/7421628

  6. 三类设计模式UML图

    http://design-patterns.readthedocs.org/zh_CN/latest/index.html

  7. 23种设计模式UML图

  8. 设计模式 UML & java code

    A: 创造性模式 1. 工厂方法模式(FactoryMethod) 1.1 类图 1.2 代码1 public interface Pet { public String petSound(); } ...

  9. 23种经典设计模式UML类图汇总

    在这里23种经典设计模式UML类图汇总       创建型模式 1.FACTORY—追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基 ...

随机推荐

  1. 在windows系统的文件右键菜单中增加“命令提示符”

    本实用小工具能够在windows系统的文件右键菜单中增加“命令提示符”,方便快速进入制定文件的命令提示窗口,避免逐层输入或复制文件夹路径,极其实用. 工具下载地址如下:360云盘(访问密码:5b71) ...

  2. Salesforce中所有常用类型字段的取值与赋值

    Salesforce中所有常用字段类型的定义以及如何用代码进行取值和赋值: Field Type的定义: http://www.salesforce.com/us/developer/docs/api ...

  3. 一个简单的Object Hook的例子(win7 32bit)

    Object Hook简单的来说就是Hook对象,这里拿看雪上的一个例子,因为是在win7 32位上的,有些地方做了些修改. _OBJECT_HEADER: kd> dt _OBJECT_HEA ...

  4. 【MyEcplise SVN】myEcplise上安装SVN的多种方式

    第一种:SVN的在线安装 1.打开MyEclipse,找到顶部菜单栏 Help(帮助)-Install from Site-(从网站安装),如下图 2. 然后: 点击Install from Site ...

  5. Maven项目在Eclipse中调试 Debug

    废话不说一路跟图走. 断点会进入到如下页面点击Edit Source Lookup Path 如下图操作 成功进入Debug模式

  6. Laravel错误与日志处理

    App\Exceptions\Handler class is where all exceptions triggered by your application are logged and th ...

  7. Codeforces Round #375 (Div. 2) - D

    题目链接:http://codeforces.com/contest/723/problem/D 题意:给定n*m小大的字符矩阵.'*'表示陆地,'.'表示水域.然后湖的定义是:如果水域完全被陆地包围 ...

  8. 通过adb命令打印log

    1.adb logcat  --打印当前设备上所有日志 2.adb logcat | findstr *** --过滤仅含***的日志 3.adb logcat *:W  --过滤打印严重级别W及以上 ...

  9. git 学习笔记6--remote & log

    git 学习笔记6--remote & log 创建SSH Keys ssh-keygen -t rsa -C "1050244110@qq.com" 本地关联远程 git ...

  10. Optimizing Performance: Data Binding(zz)

    Optimizing Performance: Data Binding .NET Framework 4.5 Other Versions   Windows Presentation Founda ...