Синхронізований блок Java для .class


103

Що означає цей код Java? Чи набере блокування на всіх об'єктах MyClass?

synchronized(MyClass.class) {
   //is all objects of MyClass are thread-safe now ??
}

І чим вищезгаданий код відрізняється від цього:

synchronized(this) {
   //is all objects of MyClass are thread-safe now ??
}

Відповіді:


144

Фрагмент synchronized(X.class) використовується екземпляр класу як монітор. Оскільки є лише один екземпляр класу (об'єкт, що представляє метадані класу під час виконання), один потік може бути у цьому блоці.

З synchronized(this)блоком охороняється екземпляр. Для кожного примірника лише один потік може входити в блок.

synchronized(X.class)використовується для того, щоб переконатися, що в блоці є рівно одна нитка. synchronized(this)гарантує наявність рівно одного потоку на примірник. Якщо це робить фактичний код у безпеці потоку блоку, залежить від реалізації. Якщо мутації достатньо лише стану екземпляра synchronized(this).


6
"стільки ниток може входити до блоку, скільки є примірник" означає, що друга форма діє як семафор, що не відповідає дійсності. Вам слід сказати щось на кшталт: "синхронізований (це) забезпечує, що лише один потік може входити в блок для заданого примірника класу".
liwp

Виправлено. Я мав намір сказати це.
Томас Юнг

2
що таке екземпляр класу проти екземпляра?
Weishi Zeng

Отже, якщо у вас є статичний метод, і ми не хочемо синхронізувати все його тіло, то ми синхронізувались (це) не добре, натомість синхронізовано (Foo.class). Це так?
krupal.agile

84

Щоб додати до інших відповідей:

static void myMethod() {
  synchronized(MyClass.class) {
    //code
  }
}

еквівалентно

static synchronized void myMethod() {
  //code
}

і

void myMethod() {
  synchronized(this) {
    //code
  }
}

еквівалентно

synchronized void myMethod() {
  //code
}

12
Друге читання мені знадобилося, щоб зрозуміти, що перші два приклади мають ключове слово "статичний". Просто вказавши це на інших, хто, можливо, це бачив і пропустив. Без статичного ключового слова перші два приклади не були б однаковими.
kurtzbot

1
Ці приклади НЕ еквівалентні! Синхронізовані методи "синхронізуються" як дірка, коли нитка намагається викликати методи. З іншого боку, блоки можуть мати код над і під ними, який може бути виконаний з декількох потоків. Вони синхронізуються лише всередині блоку! Це не те саме!
JacksOnF1re

public static Singleton getInstance () {if (instance == null) {синхронізований (Singleton.class) {instance = new Singleton (); }} повернути екземпляр; }
JacksOnF1re

2
Вся справа в тому, що там немає ніякого коду поза synchronizedблоків. Це робить їх рівнозначними. Якщо змінити один приклад, вони справді більше не є такими ж.
Джорн

23

Ні, перший отримає блокування щодо визначення класу MyClass , не у всіх його екземплярах. Однак, якщо використовується в екземплярі, це ефективно блокує всі інші екземпляри, оскільки вони поділяють одне визначення класу.

Другий отримає блокування лише в поточному екземплярі.

Що стосується того, чи це робить ваші об’єкти нитками безпечними, то це набагато складніше питання - нам потрібно буде переглянути ваш код!


1
так, MyClass.class може бути будь-якою статичною змінною і мати однаковий ефект.
pstanton

0

Так, це буде (на будь-якому синхронізованому блоці / функції).

Мене це питання цікавило пару днів (насправді в котліні). Нарешті я знайшов хороше пояснення і хочу поділитися цим:

Блокування рівня класу запобігає введенню декількох потоків у синхронізований блок у будь-який з усіх доступних екземплярів класу під час виконання. Це означає, що якщо під час виконання є 100 екземплярів DemoClass, тоді лише один потік зможе виконати demoMethod () в будь-якому з екземплярів за один раз, а всі інші екземпляри будуть заблоковані для інших потоків.

Блокування рівня класу завжди повинно здійснюватися для забезпечення безпеки статичних потоків даних. Як ми знаємо, що статичне ключове слово пов'язує дані методів із рівнем класу, тому використовуйте блокування у статичних полях або методах, щоб зробити їх на рівні класу.

Плюс помітити, чому .class . Це лише тому .class, що еквівалентно будь-якій статичній змінній класу, подібній до:

private final static Object lock = new Object();

де ім'я змінної блокування - це клас, а тип - клас <T>

Детальніше: https://howtodoinjava.com/java/multi-threading/object-vs-class-level-locking/

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.