无锁的单例

如何实现一个线程安全的单例,前提是不能加锁?

利用CAS(Compare And Swap)来实现无锁的单例。

用CAS的好处在于不需要使用传统的锁机制来保证线程安全,CAS是一种基于忙等待的算法,依赖底层硬件的实现,相对于锁它没有线程切换和阻塞的额外消耗,可以支持较大的并行度。

CAS的一个重要缺点在于如果忙等待一直执行不成功(一直在死循环中),会对CPU造成较大的执行开销。另外,如果N个线程同时执行到singleton = new Singleton();的时候,会有大量对象创建,很可能导致内存溢出。

public class Singleton {
    private static final AtomicReference<Singleton> INSTANCE = new AtomicReference<>();

    private Singleton() {
    }

    public static Singleton getInstance() {
        for (; ; ) {
            Singleton singleton =  INSTANCE.get();
            if (null != singleton) {
                return singleton;
            }

            singleton = new Singleton();
            if (INSTANCE.compareAndSet(null, singleton)) {
                return singleton;
            }
        }
    }


    //test
    public static void main( String[] args ) throws Exception{
        Singleton singleton= Singleton.getInstance();
        Singleton singleton2= Singleton.getInstance();
        System.out.printf("singleton == singleton2 ? %s\n",singleton==singleton2);

        Test test=new Test();
        Test test2=new Test();
        ExecutorService executor= Executors.newFixedThreadPool(2);
        executor.execute(test);
        executor.execute(test2);
        Thread.sleep(1000);
        Singleton singleton3=test.getValue();
        Singleton singleton4=test2.getValue();
        System.out.printf("singleton3 == singleton4 ? %s\n",singleton3==singleton4);
        System.out.printf("singleton2 == singleton4 ? %s",singleton2==singleton4);
    }
}

class Test implements Runnable{

    private Singleton singleton;
    @Override
    public void run() {
        singleton=Singleton.getInstance();
    }

    public Singleton getValue(){
        return singleton;
    }

运行结果

singleton == singleton2 ? true
singleton3 == singleton4 ? true
singleton2 == singleton4 ? true

参考

https://www.jianshu.com/p/f3fae8658f13

发布了9 篇原创文章 · 获赞 5 · 访问量 8万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览