java - 确保只有一个线程初始化对象

标签 java multithreading

我在确保对象的初始化由一个线程完成且仅一次完成时遇到了一个小问题,即下面的代码片段:

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/

相关文章:

java - 处理器和线程之间的区别

java - java.sql.Connection 线程安全吗?

java - 更改 JComboboxBox 上的 JScrollPane

java - HWPFDocument/XWPFDocument 新行

java - 如何通过 url.openStream() 发送 POST 数据?

java - 钻石运算符(operator)的默认行为是什么

c# - 线程运行时回收IIS进程

java - Java 中的并发 - 仅在一个方法上?

c# - monitor.wait 是否向其他线程发出信号

java - 从 Java 随机访问 VB6 二进制数据