Синхронизированный объект, установленный в null
У меня есть два потока Thread1
и Thread2
//Within Thread1
synchronized(obj1)
{
obj1 = null;
}
//Within Thread2
synchronized(obj1)
{
do something
}
Если jvm сначала выполняет thread1 и устанавливает obj1 в значение null, то thread2 видит это изменение немедленно или ему потребуется время, а jvm все равно может запустить синхронизированный блок thread2, поскольку obj1 еще не null?
Ответы
Ответ 1
Это почти наверняка нарушит абстракцию синхронизации - я не уверен, что thread2
увидит это изменение немедленно. Вы никогда не должны изменять ссылку на объект, который вы синхронизируете, а тем более на null
, что приведет к NullPointerException
при любых дальнейших попытках синхронизации на нем.
Ответ 2
Сначала позвольте мне подчеркнуть, что изменение переменной, используемой для синхронизации, - это ужасно плохое & trade;. obj1
должен быть final
и никогда не затрагиваться, если он используется в качестве монитора.
Сказав это, вернитесь к своему вопросу:
Если JVM сначала выполняет Thread1, он синхронизируется на obj1
, устанавливает его на null
, и поток завершается. Второй поток хочет синхронизировать на obj1
, NullPointerException
будет выбрано. Поскольку модификация obj1
была выполнена в синхронизированном блоке, гарантируется, что Thread2 увидит обновленное значение (так: NullPointerException
гарантировано).
Если Thread1 прерван после получения блокировки на obj1
, но прежде чем очистить ссылку, Thread2 закроет obj1
и дождитесь завершения Thread1. Затем он успешно войдет в монитор, потому что объект, ранее ссылающийся на obj1
, все еще существует.
Ответ 3
synchronized
синхронизирует объект, а не ссылку. Установив для параметра obj1
(reference) значение null, thread2 не может синхронизировать объект, ранее указав на obj1
, вместо этого вы получите NullPointerException
.
Ответ 4
Быстрое исправление заключается в том, чтобы сделать объект простым массивом из 1 элемента и обратиться к массиву для синхронизации, например,
Объект [] obj1 = {null};
Элемент может быть нулевым, не влияя на существование массива. Конечно, это по-прежнему нарушает "правило" не использовать сам объект в синхронизации, но если ваш код не усложняет ситуацию в другом месте, это быстрое исправление должно работать должным образом.
Ответ 5
Это немедленное изменение. Когда Thread 1 "владеет" блокировкой, он может изменить значение obj1 по желанию. Thread 2 должен ждать, пока Thread 1 освободит блокировку. Он обязательно увидит obj1 == null