JAVA多线程-通过Synchronized实现单例

 

单例模式,我们或多或少的听过或者用过,就是确保某一个对象只有一个实例,我们先看下一般的写法:

package com.ck.single;

public class Champion {

    private static final Champion champion = new Champion();

  
    private Champion() {


    }

    public static Champion getInstance() {

        return champion;

    }
}

这样写有一个缺点,就是在项目启动时Champion就已经在JVM中产生对象了,如果单例模式的类比较多,那是很占内存的,这种写法称为饿汉式,还有另外一种成为懒汉式,就是在使用的时候初始化对象。

下面我稍微修改下:

package com.ck.single;

public class Champion {

    private static Champion champion = null;

    private Champion() {

       

    }


    public static Champion getInstance() {

        if(champion == null) {

            champion = new Champion();

        }

        return champion;

    }

}

这样写虽然缓解了对象的延迟创建,在低并发的情况下可能不会出现问题,但是在高并发情况下可能会出现多个对象,这就违背了单例,什么原因呢?比如两个线程同时进入champion == null,结果判断条件都为真,那么两个线程 则产生了两个对象。

为了保证线程安全,我们引入Synchronized实现单例,我们修改代码:

package com.ck.single;

public class Champion {

    private static Champion champion = null;


    private Champion() {


    }


    public synchronized static Champion getInstance() {

        if(champion == null) {

           

            champion = new Champion();

        }

        return champion;

    }

}

上面代码的synchronized作用域是静态方法,所有属于类锁,这个我们前面已经讲过,虽然加锁了,但是在并发情况下所有线程都要同步等待,这样即使对象存在了,所有线程也要等待,所以我们需要再优化下:

package com.ck.single;

public class Champion {

   private static volatile Champion champion = null;



    private Champion() {

    }


    public  static Champion getInstance() {

        if(champion == null) {

            synchronized(Champion.class) {

                if(champion == null) {

                   champion = new Champion();

                }

            }

        }

        return champion;

    }

}

 改完后的程序,我们会发现虽然两次判断空的情况,但是提升了代码性能,因为如果对象已经存在的话就不需要等待了,而是直接返回。

猜你喜欢

转载自blog.csdn.net/cgsyck/article/details/106251614