Відповіді:
Оскільки статичний метод не має асоційованого об’єкта, чи заблокує синхронізоване ключове слово на класі замість об'єкта?
Так. :)
this
чи замок, набутий методами екземплярів, будь ласка, виправте це Оскар.
Для того, щоб додати трохи деталей до відповіді Оскара (приємно лаконічно!), Відповідний розділ у специфікації мови Java - 8.4.3.6, "Синхронізовані методи" :
Синхронізований метод набуває монітор ( §17.1 ) перед його виконанням. Для методу класу (статичного) використовується монітор, пов'язаний з об'єктом Class для класу методу. Для методу екземпляра використовується монітор, пов’язаний з цим (об'єкт, для якого було викликано метод).
Один момент, з яким ви повинні бути обережними (кілька програмістів, як правило, потрапляють у цю пастку) - це те, що між синхронізованими статичними методами та синхронізованими нестатичними методами немає зв’язку, тобто:
class A {
static synchronized f() {...}
synchronized g() {...}
}
Основні:
A a = new A();
Нитка 1:
A.f();
Нитка 2:
a.g();
f () і g () не синхронізуються один з одним і, таким чином, можуть виконуватися повністю одночасно.
synchronized (MyClass.class) {...}
.
Якщо ви не реалізуєте g () наступним чином:
g() {
synchronized(getClass()) {
...
}
}
Я вважаю цю закономірність корисною і тоді, коли хочу здійснити взаємне виключення між різними екземплярами об'єкта (що потрібно, наприклад, для доступу до зовнішнього ресурсу).
getClass()
повертає тип виконання ; якщо ви підкласируете клас, то батьківський клас і дочірній клас синхронізуються на різних блоках. synchronized(MyClass.class)
це шлях, якщо вам потрібно переконатися, що всі екземпляри використовують один і той же замок.
Перегляньте сторінку документації Oracle на тему " Внутрішні замки та синхронізація"
Вам може бути цікаво, що відбувається, коли викликається статичний синхронізований метод, оскільки статичний метод асоціюється з класом, а не об'єктом. У цьому випадку потік набуває внутрішнього блокування об’єкта Class, пов'язаного з класом . Таким чином, доступ до статичних полів класу контролюється замком, який відрізняється від блокування для будь-якого примірника класу .
Статичний метод також має пов'язаний об'єкт. Він належить файлу Class.class в наборі інструментів JDK. Коли файл .class завантажується в операційний пам'ять, Class.class створює екземпляр його під назвою об’єкт шаблону.
Наприклад: - коли ви намагаєтесь створити об'єкт із існуючого класу клієнтів, як
Customer c = new Customer();
Клас Customer.clas завантажується в оперативну пам'ять. У цей момент Class.class в наборі інструментів JDK створює об'єкт, який називається "Шаблон об'єкта", і завантажує його 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);
}
}
}
Отже, зараз у нас можуть бути такі сценарії:
Коли потоки, що використовують один і той же Object, намагаються одночасно отримати доступ до методу objLock
OR 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
Коли потоки, що використовують один і той же Object, намагаються отримати доступ 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
методу
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
Коли потоки, що використовують різні об'єкти, намагаються отримати доступ до 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
Для тих, хто не знайомий статичний синхронізований метод, заблокований на об'єкті класу, наприклад, для рядкового класу його String.class, а примірник синхронізованого методу блокується у поточному екземплярі Об'єкта, позначеному ключовим словом «це» у Java. Оскільки обидва ці об’єкти різні, вони мають різний замок, тому, коли одна нитка виконує статичний синхронізований метод, інший потік у Java не потребує очікування повернення цього потоку, а він придбає окремий замок, позначений байтом .class literal і ввійде в статичний синхронізований метод.