这就是我的代码当前的样子:

private boolean[] isInitialized = new boolean[COUNT];

private void ensureInitialized(int i) {
    if (! isInitialized[i]) {
        initialize(i);
        isInitialized[i] = true;
    }
}

现在我想拥有线程安全。我知道Java中的双重检查锁定是“ Teh 3vilness !! 1”,但是自从 ensureInitialized 可能经常被称为,我不希望它同步。所以我正在考虑这样做:

private boolean[] isInitialized = new boolean[COUNT];

private void ensureInitialized(int i) {
    if (! isInitialized[i]) {
        synchronized (this) {
            if (! isInitialized[i]) {
                initialize(i);
                isInitialized[i] = true;
            }
        }
    }
}

现在,我该怎么做才能使此线程实际安全?
一些子问题:

  • 制造 isInitialized 不需要挥发性,因为变量没有更改,对吗?
  • 阵列元素已更改,我该如何使这些动荡不安?
  • 通常有更好的方法吗?

(还请注意,这是一种实例方法,因此静态初始器将无效)

有帮助吗?

解决方案

请注意,双重检查的Java实现称为“破碎模式”,因为它被证明为失败(例如,请参见 http://www.cs.umd.edu/~pugh/java/memorymodel/doublecheckedlocking.html)。为了解决仅使用原子操作。跟随示例如何构建线程安全单例:

static AtomicReferenceArray<Boolean> instance = 
   new AtomicReferenceArray<Boolean>(COUNT);

private void ensure(int i)
{
    if(!instance.get(i) )
    {
        synchronized(this){
        if( !instance.get(i) ){
           initialize(i);
           instance.set(i, true);
        }
    }
}

其他提示

您也可以考虑使用 Suppliers.memoize(Supplier<T> delegate)番石榴图书馆.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top