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 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。
  • ¥20 CST怎么把天线放在座椅环境中并仿真