Можете ли вы безопасно синхронизировать параметры метода Java? - PullRequest
15 голосов
/ 02 июня 2011

Возьмите этот код:

public class MyClass {
    private final Object _lock = new Object();
    private final MyMutableClass _mutableObject = new MyMutableClass()

    public void myMethod() {
        synchronized(_lock) { // we are synchronizing on instance variable _lock
            // do something with mutableVar 
            //(i.e. call a "set" method on _mutableObject)
        }
    }
}

. Теперь представьте, что делегируете код внутри myMethod () какому-то вспомогательному классу, где вы передаете блокировку

public class HelperClass {
    public helperMethod(Object lockVar, MyMutableClass mutableVar) {
        synchronized(lockVar) { // we are now synchronizing on a method param, 
                                // each thread has own copy
            // do something with mutableVar 
            // (i.e. call a "set" method on mutableVar)
        }
    }
}

, может ли "myMethod" быть повторнонаписано для использования HelperClass, передавая его блокировку var, так что все по-прежнему потокобезопасным?то есть

public void myMethod() {
    _helperObject.helperMethod(_lock, _mutableObject);
}

Я не уверен в этом, потому что Java передаст значение lockVar по значению, и каждый поток получит отдельную копию lockVar (даже если каждая копия указывает на один и тот же объект в куче).).Я предполагаю, что вопрос сводится к тому, как работает ключевое слово «synchronized» - блокирует ли оно переменную или значение в куче, на которое ссылается переменная?

1 Ответ

9 голосов
/ 02 июня 2011

Синхронизация выполняется для объектов , а не переменных .

Переменные / члены [иногда] содержат объекты и именно результирующий объект , содержащийся в [переменная] x, фактически синхронизируется в synchronized(x).

Есть несколько других проблем с видимостью переменных переменных (например,может считывать «устаревший» объект из переменной), но это не применимо: здесь нет повторного назначения _lock и видимость начального («конечного») назначения гарантируется.Благодаря этому гарантируется, что в этом случае параметр метода всегда будет содержать правильный (один и тот же) объект , используемый для синхронизации.

Если используется объект блокировки (где предположительно *)1022 * не является окончательным), однако это потребует переоценки соответствующих значений / видимости потока, но в остальном не отличается от любого межпоточного доступа.

Счастливое кодирование.

...