JAVA设计模式---单态模式理解

前言

何为单态模式?
在一个系统中,JVM中,只能存在有一个对象的实例,所有程序的处理都只能调用这一个对象完成相关逻辑操作,单态模式有点在于减少了new关键字的调用,实例的初始化,节省了系统内存开销。单态模式的难点在于多线程的处理,写法很多,真正能够执行的,考虑的,难点在于线程的安全问题!!!,本文进行简单的理解阐述,如果不明白,请关注博主留下的两篇好文

两篇好文

http://www.blogjava.net/kenzhh/archive/2013/03/15/357824.html
http://www.cnblogs.com/dolphin0520/p/3920373.html

单态模式的正确实现

public class Truth {
    //volatitle 保证修饰变量在内存中的可见性,与java内存模型配合
    //volatile关键字能禁止指令重排序,所以volatile能在一定程度上保证有序性
    private volatile static Truth instance = null;
    private Truth(){}
    public static Truth getInstance(){
        if(instance == null){
            //保证原子性操作
            synchronized (Truth.class){
                if(instance == null) {
                    instance = new Truth();
                }
            }
        }
        return instance;
    }

    public void say(){
        System.out.println("only one truth in the world!");
    }
}

简单阐述

1-私有变量instance只能在内部进行初始化操作,
2-当instance为空的时候进行一次变量赋值,从而保证返回对象不可为空

多线程相关

1-double check [volatile|synchronized ]保证该类的线程安全
2-可能出现的问题为,当两个线程同时进入getInstance方法时,线程1进行了判断但是没有赋值,线程2则执行下去并且赋值的同时,两个线程没有对公共变量进行同步,那么线程1回来继续执行的同时会直接new出来第二个实例,当然,这是在double check没有约束的时候

synchronized关键字简单阐述

保证了原子性的操作,被该关键字修饰以后的代码中,在一个时间内只能有一个线程进行执行,当执行完成以后,线程将最新的值更新到内存中才放行第二个线程进入代码块中执行

volatile关键字简单阐述

保证了线程的有序性和可见性,被该关键字修饰的变量,在所有的线程操作中将都是可见的,也就是说从CPU中的高速缓存载入执行以后,引起的更改将会通知到其他CPU的高速缓存,在这些CPU的高速缓存中将会做失效状态标记,从而引起其他线程执行到该变量时,从内存中重新载入高速缓存.

可见性

什么叫可见性,如图所示,当多线程处理的时候,把变量值以及相关程序载入到高速缓存中,由CPU进行处理,当程序对内存中的值进行变更处理以后,在没有刷新到缓存之前,其他的线程进行读取并操作的处理,这时候会造成读取的值并不是最新的,进而引发线程安全问题,这也就是线程的可见性
这里写图片描述

有序性

有序性理解为程序执行的顺序问题,在编码的时候,我们所有的程序一般是顺序执行,在载入JVM中,包括后面的实际执行中,会将我们程序执行的顺序打乱,并且提高执行效率,在单线程处理中,我们并不需要考虑有序性的执行,但是多线程中,往往会因为程序的执行顺序造成线程的不安全问题,比如程序之间不存在程序依赖关系,但是存在逻辑依赖关系,此时则会造成线程安全问题。

原子性

原子性处理,即为要么不处理,要么所有的程序处理完成,整个程序为一个整体,类似于数据库的事务,但是,该程序不会发生回滚,原子性是多线程处理中的必不可少的一环.

猜你喜欢

转载自blog.csdn.net/zhang6622056/article/details/52611242