0

问题 1:为什么在多线程的单例模式中我们需要两个空值检查?如果我们只使用外部检查怎么办?

    if (instance == null) {
        synchronized (ABC.class) {

            // What if we remove this check?
            if (instance == null) {
                instance = new ABC();
            }
    }

问题2:以下有什么区别:

1:直接使用synchronized()里面的类名

    public ABC getInstance() {
        if (instance == null) {
            // Difference here
            synchronized (ABC.class) {
                if (instance == null) {
                    instance = new ABC();
                }
            }
         }
         return instance;
    }

2:在 synchronized() 中使用静态最终对象

    private static final Object LOCK = new Object();
    .
    .
    public ABC getInstance() {
        if (instance == null) {

             // Difference here
             synchronized (LOCK) {
                if (instance == null) {
                    instance = new ABC();
                }
             }
         }
         return instance;
    }

3:在 synchronized() 中使用new Object( )

    if (instance == null) {
    // Difference here
         synchronized (new Object()) {
            if (instance == null) {
                instance = new ABC();
            }
        }
     }
4

1 回答 1

-1
  1. 删除内部 nullcheck 可能会导致竞争条件。想象以下场景:两个线程试图同时获取对象的实例,因此它们都检查实例是否等于 null 并得到正确的答案,因此两个线程都将尝试创建对象的实例。因为这段代码是同步的,所以其中一个线程将进入同步的代码块,而另一个等待锁被释放。当第一个线程完成实例化并返回对象的实例后,锁将被释放,第二个线程将执行同步块,因此它将创建一个新实例并返回它,因为它不知道它之前已创建在它等待轮到它的时候。
  2. 在 synchronized 中使用类作为参数将生成一个静态锁。这意味着该类的所有实例都将共享锁。
  3. 如果您想用特定对象而不是类或 this 锁定同步块,则使用对象作为同步参数是有用的。这允许您在同一类中使用不同的锁来拥有不同的代码块。例如:

    Object o1 = new Object();
    Object o2 = new Object();
    synchronized(o1) {
        //your synchronized block
     }
    
    synchronized(o2){
        //other synchronized block
    }
    

在前面的代码示例中,block1 和 block2 可以由不同的线程同时执行,因为它们使用不同的锁对象。如果您对两个代码块(即类)使用相同的锁,则块 1 将被阻塞,直到块 2 完成其执行,反之亦然。

于 2019-07-05T22:51:59.547 回答