如何在线程安全延迟初始化期间避免持续同步(不是单例解决方案)?

Ant*_*sss 5 java concurrency multithreading synchronization lazy-initialization

我想知道以下情况的最佳方法是什么:

可以说,我们有一些工厂MyUtilFactory返回MyUtil类的缓存实例.多个实例MyUtil在一个static Map<String,MyUtil> utilsCache.

现在,懒惰创建的抽象流程应该如下:

  1. 如果缓存utilsCache为空,则执行第一次初始化 - 将实例加载到静态缓存映射.
  2. 从缓存中获取实例
  3. 检查检索的实例是否已初始化
  4. 如果实例未初始化,则执行实例​​初始化(昂贵)
  5. 返回实例.

现在,步骤1和4需要同步,因为初始化是耗时的并且它将被执行多次,但是仅需要第一次初始化缓存和实例.

很容易将所有内容放在同步块(甚至方法)中,根本不存在任何问题,但是我希望避免在不需要的情况下进行同步.

一种方法就是这样

        if (!someObject.isInitialized()) { // check if it is ready without synchonization
            synchronized (someObject) { // its not ready so lets synchronize from here
                if (!someObject.isInitialized()) { //first thread will get the samo outcome, but other threads will not
                    performInitialization();
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)

现在,在synchronized块中重复条件的重点是允许第一个线程进行初始化.任何后续线程将等待第一个线程完成初始化,而不是条件为synchronized,如果不满足statment.它可以像这样完成它并且运作良好,但我认为这不是最好和最优雅的方法来解决这个问题.我的问题是,如何做到"正确的方式"

ven*_*iac 5

是的,正确的双重检查锁定也是正确的方法

http://en.wikipedia.org/wiki/Double-checked_locking

"someObject.isInitialized()"有一点问题:"someObject"在java 6中必须是volatile.

 private volatile SomeObject someObject= null;
Run Code Online (Sandbox Code Playgroud)

阅读这篇文章非常有用

http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html