Статические методы, синхронизированные с Java:блокировка объекта или класса
-
22-07-2019 - |
Вопрос
В руководствах по Java говорится:"чередование двух вызовов синхронизированных методов для одного и того же объекта невозможно".
Что это означает для статического метода?Поскольку статический метод не имеет связанного объекта, будет ли ключевое слово synchronized блокировать класс, а не объект?
Решение
Поскольку статический метод не имеет связанного объекта, будет ли ключевое слово synchronized блокировать класс, а не объект?
ДА.:)
Другие советы
Просто для того, чтобы добавить немного деталей к ответу Оскара (приятно лаконично!), соответствующий раздел в спецификации языка Java: 8.4.3.6,« синхронизированные методы »:
Синхронизированный метод получает монитор (& # 167; 17.1) до его выполнения. Для метода класса (статического) используется монитор, связанный с объектом Class для класса метода. Для метода экземпляра используется связанный с ним монитор (объект, для которого был вызван метод). Р>
Один момент, с которым вы должны быть осторожны (несколько программистов обычно попадают в эту ловушку), заключается в том, что нет связи между синхронизированными статическими методами и синхронизированными нестатическими методами, т.е.:
class A {
static synchronized f() {...}
synchronized g() {...}
}
Главная:
A a = new A();
Резьба 1:
A.f();
Поток 2:
a.g();
f() и g() не синхронизированы друг с другом и, следовательно, могут выполняться полностью одновременно.
Если вы не реализуете g () следующим образом:
g() {
synchronized(getClass()) {
...
}
}
Я считаю этот шаблон полезным, когда я хочу реализовать взаимное исключение между различными экземплярами объекта (например, это необходимо при доступе к внешнему ресурсу).
Статический метод также имеет связанный объект. Он принадлежит файлу Class.class в наборе инструментов JDK. Когда файл .class загружается в оперативную память, Class.class создает экземпляр этого объекта, который называется шаблоном.
Например: - когда вы пытаетесь создать объект из существующего класса клиента, например
Customer c = new Customer();
Класс Customer.class загружается в оперативную память. В этот момент Class.class в JDK toolkit создает объект с именем Template и загружает этот Customer.class в этот объект шаблона. Статические члены этого Customer.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);
}
}
}
Итак, теперь у нас могут быть следующие сценарии:
<Ол> Когда потоки, использующие один и тот же объект , пытаются получить доступ к методу objLock
ИЛИ 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
Когда потоки, использующие один и тот же объект , пытаются получить доступ к методам 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
Когда потоки, использующие другой объект , пытаются получить доступ к методу staticLock
Когда потоки, использующие другой объект , пытаются получить доступ к методу objLock
Для тех, кто не знаком, статический синхронизированный метод заблокирован на объекте класса, например. для строкового класса его String.class, в то время как метод синхронизации экземпляров блокирует текущий экземпляр объекта, обозначенный в Java ключевым словом this. Поскольку оба эти объекта различны, они имеют разную блокировку, поэтому, пока один поток выполняет статический синхронизированный метод, другому потоку в java не нужно ждать возврата этого потока, вместо этого он получит отдельную блокировку, обозначенную байтом .class, и войдет в статический синхронизированный метод. Р>