首页 > 编程语言 > 详细

多线程下的单例模式

时间:2019-05-17 23:18:06      阅读:113      评论:0      收藏:0      [点我收藏+]

单例的实现

1.单线程下的Lazy实现

public class Main {
    private static Main instance = null;
    
    private Main() {}
    
    public static Main getInstance() {
        if(null == instance) instance = new Main();
        return instance;
    }
}

2.针对1的多线程阻塞实现

就是改进了check-then-act的原子性问题

public class Main {
    private static Main instance = null;
    
    private Main() {}
    
    public static Main getInstance() {
        synchronized(Main.class) {
            if(null == instance) instance = new Main();
        }
        return instance;
    }
}

3.错误的双重加锁

public class Main {
    private static Main instance = null;
    
    private Main() {}
    
    public static Main getInstance() {
        if(null == instance) synchronized(Main.class) {
            if(null == instance) instance = new Main(); // 问题出现在初始化
        }
        return instance;
    }
}

注意可见性是正确的,错误在于初始化的重排序

上一篇文章已经写了3个步骤,一个线程在判断第一个if的时候可能另一个线程执行到第二个步骤就写入引用了,这时返回的是默认值

4.正确的双重加锁

既然重排序有问题那当然要volatile

public class Main {
    private static volatile Main instance = null;
    
    private Main() {}
    
    public static Main getInstance() {
        if(null == instance) synchronized(Main.class) {
            if(null == instance) instance = new Main();
        }
        return instance;
    }
}

5.静态内部类

利用class文件对于内部类的特性,实现上够简单

public class Main {
    
    private static class InstanceHolder {
        final static Main INSTANCE = new Main();
    }
    
    public static Main getInstance() {
        return InstanceHolder.INSTANCE;
    }
}

6.枚举类

仅访问Singleton本身不会使Singleton.INSTANCE初始化

public enum Singleton {
    INSTANCE;
    Singleton() {}
    public void doSomething() {}
}

public class Main {
    public static void main() {
        new Thread() {
            public void run() {
                Singleton.INSTANCE.doSomething();
            }
        }.start();
    }
    
}

懒汉?饿汉?

补充一下奇怪的术语:懒汉式、饿汉式

其中懒汉式就是带Lazy加载的意思,比如1、2

而饿汉式我并不太清楚字面上的意思。。应该是指内存宽裕吧。。就是static直接返回的那种,显然不如静态内部类

public class Main {
    private static Main instance = new Main();
    private Main() {}
    public static Main getInstance() { return instance; }
}

破坏单例模式

1.除了enum和静态内部类,其它都可以被newInstance()拿到手

改进方法就是在构造方法创建保护null的判断

2.还有一种反序列化的破坏方式(如果你的单例需要序列化)。。

解决方法是重写readResolve()方法,使得它在方法内直接返回instance

多线程下的单例模式

原文:https://www.cnblogs.com/caturra/p/10884130.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!