문제

This is what my code currently looks like:

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

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

Now I want to have it thread-safe. I know that double-checked-locking in Java is "teh 3vilness!!1", but since ensureInitialized may be called very often, I don't want it to be synchronized. So I am thinking of doing this:

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

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

Now what do I have to do to make this actually thread safe?
Some subquestions:

  • Making isInitialized volatile is not necessary, since the variable is not changed, right?
  • The array elements are changed, how can I make those volatile?
  • Are there generally better ways to do this?

(Also notice that this is an instance method, so static initializer will no work)

도움이 되었습니까?

해결책

Please note that java implementation of double-checking is called "broken pattern" because it was proven as fail (for example see http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html). To work around just use atomic operation. Follow is sample how to build thread safe singleton:

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);
        }
    }
}

다른 팁

You could also consider using Suppliers.memoize(Supplier<T> delegate) from guava library.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top