2012-04-17 2 views
20

У меня есть две темы Thread1 и Thread2синхронизируется объект установлен в нуль

//Within Thread1  
synchronized(obj1) 
{ 
    obj1 = null; 
} 

//Within Thread2 
synchronized(obj1) 
{ 
    do something 
} 

Если JVM сначала выполняет thread1 и устанавливает obj1 в нуль, то будет thread2 видеть, что изменение немедленно или это займет время и JVM все еще может работать синхронизированный блок thread2, поскольку obj1 еще не null?

+7

@ Korhan ...ztürk Он не мог попробовать себя, любой вопрос, связанный с параллелизмом, не детерминирован. Эти типы комментариев чрезвычайно расстраивают, когда контекст неизвестен. –

ответ

28

Это почти наверняка нарушит абстракцию синхронизации - я не уверен, что thread2 увидит изменение немедленно. Вы никогда не должны менять ссылку на объект, который вы синхронизируете, а тем более на него устанавливаете null, что приведет к возникновению NullPointerException при любых дальнейших попытках синхронизации на нем.

9

Прежде всего позвольте мне подчеркнуть, что изменение переменной, используемой для синхронизации, является ужасно плохой вехой ™. obj1 должен быть final и никогда не быть затронут, если он используется в качестве монитора.

Это, как говорится, вернемся к вашему вопросу:

Если JVM сначала выполняет thread1, он синхронизирует на obj1, устанавливает его null и выходов резьбы. Второй поток хочет синхронизировать на obj1, NullPointerException будет выброшен. Поскольку модификация obj1 была выполнена в синхронизированном блоке, гарантируется, что Thread2 увидит обновленное значение (так: NullPointerException гарантировано).

Если Thread1 прерван после получения блокировки на obj1, но перед очисткой ссылки Thread2 закроется на obj1 и дождитесь окончания Thread1. Затем он успешно войдет в монитор, потому что объект, ранее ссылающийся на obj1, все еще существует.

+0

Поскольку obj1 используется в синхронизированном состоянии, а не в синхронизированном блоке, невозможно ли, чтобы оба потока пытались синхронизировать в одно и то же время, а thread1 входит первым, а thread2 кэширует значение obj1.когда thread1 выходит из thread2, берет значение obj1 из кэша и входит в синхронизированный блок и видит изменение внутри синхронизированного блока. – vjk

+0

@Tomsaz. Я не получил эту инструкцию. _If Thread1 прерван после получения блокировки на obj1, но перед очисткой ссылка, Thread2 будет блокироваться на obj1 и ждать, пока Thread1 не закончит. Теперь мы в первую очередь прерываем поток только тогда, когда они заблокированы, и в любом случае, если они не заблокированы, прерывание их не влияет, не так ли? В принципе, я никогда не вижу случая, когда thread1 откажется от блокировки без завершения синхронизированного блока или без wait(), вызывающего эту блокировку. IOW, когда и почему thread2 получит блокировку, но все равно будет ждать завершения thread1. – sactiw

4

synchronized синхронизирует объект, а не ссылку. Установив obj1 (ссылка) на null, thread2 не может синхронизировать объект, ранее указавший на obj1, вместо этого вы получите NullPointerException.

0

Изменение немедленное. Когда Thread 1 «владеет» блокировкой, он может изменить значение obj1 по желанию. Thread 2 должен ждать, пока Thread 1 освободит блокировку. Это будет определенно видеть obj1 == NULL

1

Быстрое исправление, чтобы сделать объект простой массив из 1 элемента и ссылаться на массив для синхронизации, например,

Object [] obj1 = {NULL};

Элемент может быть нулевым, не влияя на существование массива. Конечно, это по-прежнему нарушает «правило» не использовать сам объект в синхронизации, но если ваш код не усложняет ситуацию в другом месте, это быстрое исправление должно работать должным образом.

Смежные вопросы