Синхронизированные статические методы Java: блокировка объекта или classа

Учебники Java говорят: «невозможно, чтобы две вызовы синхронизированных методов на одном и том же объекте чередовали».

Что это означает для static method ? Поскольку у статического метода нет связанного объекта, будет ли синхронизированная блокировка ключевого слова для classа вместо объекта?

Поскольку у статического метода нет связанного объекта, будет ли синхронизированная блокировка ключевого слова для classа вместо объекта?

Да. 🙂

Чтобы добавить немного подробностей в ответ Оскара (приятный лаконичный!), Соответствующий раздел спецификации языка Java – это 8.4.3.6, «synchronized Methods» :

Синхронный метод получает монитор (§17.1) перед его выполнением. Для classа (статического) метода используется монитор, связанный с объектом classа для classа метода. Для метода экземпляра используется связанный с ним монитор (объект, для которого был вызван метод).

Один момент, о котором вы должны быть осторожны (несколько программистов, как правило, попадают в эту ловушку), заключается в том, что между синхронизированными статическими методами и синхронизованными нестационарными методами нет связи, т. Е.

 class A { static synchronized f() {...} synchronized g() {...} } 

Главный:

 A a = new A(); 

Тема 1:

 Af(); 

Тема 2:

 ag(); 

f () и g () не синхронизированы друг с другом и, таким образом, могут выполняться полностью одновременно.

Если вы не реализуете g () следующим образом:

 g() { synchronized(getClass()) { ... } } 

Я считаю, что этот шаблон полезен также, когда я хочу реализовать взаимное исключение между различными экземплярами объекта (что необходимо, например, при подключении внешнего ресурса).

Взгляните на страницу документации oracleа на встроенные блокировки и синхронизацию

Вы можете задаться вопросом, что происходит, когда вызывается статический синхронизированный метод, поскольку статический метод связан с classом, а не с объектом. В этом случае stream получает встроенный замок для объекта Class, связанного с classом . Таким образом, доступ к статическим полям classа контролируется блокировкой, отличной от блокировки для любого экземпляра classа .

Ниже примеры дают большую ясность между блокировкой объектов и объектов, надеюсь, что ниже пример поможет и другим 🙂

Например, мы имеем ниже методы: один приобретает class и другую блокировку объекта:

 public class MultiThread { public static synchronized void staticLock() throws InterruptedException { for (int i = 0; i < 10; i++) { Thread.sleep(100); System.out.println(Thread.currentThread().getName() + " " + i); } } public synchronized void objLock() throws InterruptedException { for (int i = 0; i < 10; i++) { Thread.sleep(100); System.out.println(Thread.currentThread().getName() + " " + i); } } } 

Итак, теперь у нас могут быть следующие сценарии:

  1. Когда streamи, использующие один и тот же объект, пытаются одновременно получить доступ к objLock или staticLock (т.е. оба streamа пытаются получить доступ к одному и тому же методу)

     Thread-0 0 Thread-0 1 Thread-0 2 Thread-0 3 Thread-0 4 Thread-1 0 Thread-1 1 Thread-1 2 Thread-1 3 Thread-1 4 
  2. Когда streamи, использующие один и тот же объект, пытаются staticLock objLock методам staticLock и objLock (пытается получить доступ к различным методам)

     Thread-0 0 Thread-1 0 Thread-0 1 Thread-1 1 Thread-0 2 Thread-1 2 Thread-1 3 Thread-0 3 Thread-0 4 Thread-1 4 
  3. Когда streamи, использующие другой объект, пытаются получить доступ staticLock методу staticLock

     Thread-0 0 Thread-0 1 Thread-0 2 Thread-0 3 Thread-0 4 Thread-1 0 Thread-1 1 Thread-1 2 Thread-1 3 Thread-1 4 
  4. Когда streamи, использующие другой объект, пытаются получить доступ objLock методу objLock

     Thread-0 0 Thread-1 0 Thread-0 1 Thread-1 1 Thread-0 2 Thread-1 2 Thread-1 3 Thread-0 3 Thread-0 4 Thread-1 4 

У статического метода также есть связанный объект. Он принадлежит к файлу Class.class в наборе инструментов JDK. Когда файл .class загружается в ram, Class.class создает экземпляр, который называется объектом шаблона.

Например: когда вы пытаетесь создать объект из существующего classа клиента, например

 Customer c = new Customer(); 

Загрузка Customer.class в оперативную память. В этот момент Class.class в наборе инструментов JDK создает объект, называемый объектом Template, и загружает этот объект Customer.class в этот объект шаблона. Статические члены этого classа Customer.class становятся атрибутами и методами в этом объекте шаблона.

Таким образом, статический метод или атрибут также имеет объект

Для тех, кто не знаком статический синхронизированный метод, заблокированный объектом classа, например, для строкового classа его String.class, а синхронизированный метод экземпляра блокирует текущий экземпляр объекта, обозначенного ключевым словом this this в Java. Поскольку оба этих объекта различны, они имеют разную блокировку, поэтому, когда один stream выполняет статический синхронизированный метод, другому streamу в java не нужно ждать, пока этот stream вернется, вместо этого он получит отдельный замок, обозначенный байтом .class literal, и введите статический синхронизированный метод.

  • Java: статический и внутренний class
  • Является ли инициализация статической членской переменной C ++ streamобезопасной?
  • Почему Mockito не издевается над статическими методами?
  • глобальная переменная в C статична или нет?
  • Разница между статическими методами и методами экземпляра
  • Разница между статическими и частными статическими переменными
  • Spring: обслуживание статических ресурсов вне контекста root
  • Могут ли нестатические методы изменять статические переменные
  • «Нестатический метод не может ссылаться на статический контекст»
  • Какова цель статического ключевого слова в параметре массива функции типа «char s »?
  • Что такое «статический метод» в C #?
  • Давайте будем гением компьютера.