Меня интересует, как синхронизируется работает в смысле, как / когда он сбрасывает записи из локальных кэшей.
На самом деле, synchronized
не сбрасывает записи из локальных кэшей.Это просто действует так, как если бы это было так.
Все ли три примера имеют один и тот же уровень "безопасности потока" (принимая во внимание особенности, такие как первая запись выполняется одним потоком, а вторая запись выполняется после первойодин (не так ли?) и другой поток), т. е. «гарантировано ли напечатано 10»?
Все они обеспечивают несколько разные формы безопасности потока.Ни один из них не является действительно безопасным, если другие потоки одновременно обращаются к объекту.Например, другой поток, обращающийся к counter
, должен будет удерживать блокировки String.class
и Integer.class
, чтобы гарантировать, что он не видит counter
во время операции.Третий использует операции приращения, которые не являются атомарными, хотя это безопасно, если никакой другой поток не пытается изменить counter
.
Есть ли разница в производительности (по крайней мере теоретическая) в «работе» внесинхронизированный блок или работа с энергонезависимыми свойствами (я бы ожидал, что энергозависимый доступ будет медленнее, как подтверждает этот пост), но в случае синхронизированного блока это «сбрасываемая» цена, выплачиваемая только при пересечении синхронизированного начала / конца, или есть также разница, когда внутриблок?
без разницы.Ввод блока synchronized
требует определенных затрат, поскольку блокировка должна быть получена, а некоторые оптимизации должны быть отключены в точке входа.Выход из блока сопряжен с аналогичными затратами.
Внутри блока нет затрат, потому что программист обеспечивает безопасность, гарантируя, что они не позволяют никакому потоку изменять объект, если он не имеет такой же блокировки и не имеет двухпотоки могут одновременно удерживать одну и ту же блокировку.Вообще говоря, код может даже не знать, находится ли он внутри одного или нескольких блоков synchronized
, потому что он может находиться глубоко в дереве вызовов.