Краткий ответ: нет, они не будут правильно блокироваться / разблокироваться, и таких подходов следует избегать.
Мой первый вопрос: почему вы хотите сделать что-то подобное, так как эти подходы сводят на нет цели и преимущества использования @synchronized-блока в первую очередь.
Во втором примере, когда поток изменяет значение obj
, каждый последующий поток, который достигает блока @synchronized, будет синхронизироваться с новым объектом, а не с исходным объектом. Для N потоков вы явно создадите N автоматически выпущенных объектов, и среда выполнения может создать до N рекурсивных блокировок, связанных с этими объектами. Обмен объекта, с которым вы синхронизируете в критическом разделе, является принципиальным отказом от потокобезопасного параллелизма. Не делай этого. Когда-либо. Если несколько потоков могут безопасно обращаться к блоку одновременно, просто полностью опустите @synchronized.
В вашем первом примере результаты могут быть неопределенными, и, конечно, не такими, как вы хотите. Если среда выполнения использует только указатель объекта для поиска связанной блокировки, код может работать нормально, но синхронизация на nil
не имеет ощутимого эффекта в моих простых тестах, поэтому снова вы используете @synchronized бессмысленным образом, поскольку не предлагает никакой защиты.
Честно говоря, я не пытаюсь быть резким, так как я полагаю, что вам, вероятно, просто интересно узнать о конструкции. Я просто формулирую это решительно, чтобы (надеюсь) помешать вам и другим людям писать код, который является фатальным, особенно если предполагается, что он синхронизируется должным образом. Удачи!