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