我在确保对象的初始化由一个线程完成且仅一次完成时遇到了一个小问题,即下面的代码片段:
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 block 中,因为现在如果发生异常,线程mnight就会卡住。然而,即使使用finally block ,线程也会被释放,系统将处于未初始化状态。是否有可遵循的模式来做到这一点?
最佳答案
我建议从一个简单而正确的解决方案开始。如果性能确实很重要,您可以事后对其进行优化。一个简单的解决方案可能如下所示:
private final Object lock = new Object();
private boolean initialized = false;
void init() {
synchronized (lock) {
if (!initialized) {
someMethod();
initialized = true;
}
}
}
如果性能很重要,您可以添加对 boolean 变量的额外检查,该检查使用 volatile 变量而不是同步块(synchronized block)。这种模式称为双重检查锁定:
private final Object lock = new Object();
private volatile boolean initialized = false;
void init() {
if (!initialized) {
synchronized (lock) {
if (!initialized) {
someMethod();
initialized = true;
}
}
}
}
关于java - 确保只有一个线程初始化对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24189408/