Intereting Posts

Синхронизированный метод Java

Рассмотрим этот код:

public synchronized void onSignalsTimeout(List<SignalSpec> specs) { if (specs != null && specs.size() > 0) { for (SignalSpec spec : specs) { ParsedCANSignal timeoutedSignal = new ParsedCANSignal(); SignalsProvider.getInstance().setSignal(spec.name, spec.parent.parent.channel, timeoutedSignal); } } } 

У меня есть простой вопрос: когда Thread 1 вызывает метод onSignalsTimeout, могут ли объекты доступа Thread 2, к которым обращаются в этом методе?

Не удается найти нигде, если «synchronized» блокирует доступ только к этому методу или доступ ко всем объектам, используемым в этом методе.

Solutions Collecting From Web of "Синхронизированный метод Java"

Прежде всего, забудьте о синхронизированных методах . Так называемый синхронный метод …

 synchronized AnyType foobar(...) { doSomething(); } 

Это не что иное, как быстрый способ написания этого:

 AnyType foobar(...) { synchronized(this) { doSomething(); } } 

В этом случае нет ничего особенного в этом методе . Особенностью является синхронизированный блок , и что делает синхронизированный блок очень простым. Когда JVM выполняет это:

 synchronized(foo) { doSomething(); } 

Сначала он вычисляет выражение foo . Результат должен быть ссылкой на объект. Затем он блокирует объект, выполняет тело synchronized блока, а затем он разблокирует объект.

Но что заперто ? Это может означать меньше, чем вы думаете. Это не мешает другим потокам использовать объект. Это не мешает им получать доступ к полям объекта или, обновляя его поля. Единственное, что предотвращает блокирование объекта, – это предотвращение одновременного блокирования других потоков одним и тем же объектом.

Если поток A пытается ввести synchronized(foo) {...} тогда как поток B уже заблокирован foo (либо в том же synchronized блоке, либо в другом), тогда поток A будет вынужден ждать, пока поток B не освободит замок.


Для защиты данных используются synchronized блоки.

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

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

Если вы поместите код, который изменяет состояние в synchronized(foo) блоке, и вы помещаете каждый блок кода, который может видеть состояние в синхронизированный блок, который блокирует один и тот же объект , foo , то вы предотвратите просмотр других потоков Временное недействительное состояние.

Да, другие потоки могут обращаться к объектам, используемым в методе; Ключевое слово synchronized гарантирует, что не более одного потока в то время может выполнить код метода.

Из https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html :

  • Во-первых, невозможно, чтобы две вызовы синхронизированных методов на одном объекте чередовали. Когда один поток выполняет синхронизированный метод для объекта, все остальные потоки, которые вызывают синхронизированные методы для одного и того же объекта (приостанавливать выполнение) до тех пор, пока первый поток не будет выполнен с объектом.
  • Во-вторых, когда синхронизированный метод завершается, он автоматически устанавливает связь между событиями и последующим вызовом синхронизированного метода для одного и того же объекта. Это гарантирует, что изменения состояния объекта будут видны для всех потоков. Обратите внимание, что конструкторы не могут быть синхронизированы – использование синхронизированного ключевого слова с конструктором является синтаксической ошибкой. Синхронизация конструкторов не имеет смысла, потому что только поток, который создает объект, должен иметь к нему доступ во время его создания.

В этом контексте synchronized одновременно блокирует этот метод и любой другой метод, аналогично помеченный как synchronized в вашем классе.