我在确保对象的初始化是由一个线程完成并且只有一次(即在下面的代码段中给出)时遇到一个小问题:

AtomicBoolean initialize = new AtomicBoolean();
CountDownLoatch latch = new CountDownLatch(1);

void init(){
     if(initialize.compareAndSwap(false,true)) {
          someMethod() // this can throw some exception
          latch.countDown();
      }
      else{
          latch.await();
      }
}


我可以将倒计时包装在finally块中,因为如果发生异常,则线程mnight会卡住。但是,即使使用finally块,该线程也将被释放,并且系统将处于未初始化状态。有没有遵循的模式可以解决这个问题?

最佳答案

我建议从一个简单而正确的解决方案开始。如果性能确实很重要,则可以在以后对其进行优化。一个简单的解决方案可能如下所示:

private final Object lock = new Object();
private boolean initialized = false;

void init() {
    synchronized (lock) {
        if (!initialized) {
            someMethod();
            initialized = true;
        }
    }
}


如果性能很重要,则可以添加对布尔变量的附加检查,该检查使用易失性变量而不是同步块。这种模式称为双重检查锁定:

private final Object lock = new Object();
private volatile boolean initialized = false;

void init() {
    if (!initialized) {
        synchronized (lock) {
            if (!initialized) {
                someMethod();
                initialized = true;
            }
        }
    }
}

10-05 19:32