weixin_46032763 2020-03-18 14:04 采纳率: 0%
浏览 96

请问线程安全懒汉式单例模式能这样写么谢谢

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

    @Override
    public String toString() {
        return super.toString();
    }
}
public class ConsumerTest {
    public static void main(String[] args) {
        System.out.println(Consumer.getInstance());
        System.out.println(Consumer.getInstance());
        System.out.println(Consumer.getInstance());
    }
}
  • 写回答

1条回答 默认 最新

  • 有头发的猿 2020-03-18 14:33
    关注

    你这个写法是线程不安全的,是有问题的,
    当你的getInstance在不同线程中分别调用时,假如线程1走到了consumer=new Consumer();这行代码,这个时候Cpu将运行机会分配了线程2,
    线程2 走到 synchronized (Consumer.class) { 这行代码,发现代码锁住了,因为线程1正在里面,于是乎wait住了,于是线程1继续执行,
    创建了一个 consumer 对象,这个时候线程1已经完全执行完成,线程2也发现 synchronized 已经 没有锁住了,于是接着执行,这样的话 就又创建了一个consumer对象,所以正确的写法应该是如下:

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

    在同步锁后面在使用一个null判断,保证线程2起来后,发现对象已经不为null,因此避免了重复创建。

    评论

报告相同问题?

悬赏问题

  • ¥15 用三极管设计—个共射极放大电路
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示