Java: Как сделать двойную проверку-блокировку с элементом массива? - PullRequest
1 голос
/ 09 октября 2010

Вот как выглядит мой код:

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

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

Теперь я хочу, чтобы это было поточно-ориентированным. Я знаю, что двойная проверка блокировки в Java - это «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 volatile не нужно, поскольку переменная не изменяется, верно?
  • Элементы массива изменены, как я могу сделать их изменчивыми?
  • Есть ли вообще лучшие способы сделать это?

(Также обратите внимание, что это метод экземпляра, поэтому статический инициализатор работать не будет)

Ответы [ 2 ]

3 голосов
/ 26 января 2011

Вы также можете использовать Suppliers.memoize(Supplier<T> delegate) из библиотеки гуавы .

1 голос
/ 09 октября 2010

Обратите внимание, что реализация двойной проверки в 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);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...