Question

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)

Was it helpful?

Solution

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

OTHER TIPS

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top