Zsynchronizowany blok Java dla .class

Odpowiedzi:

144

Fragment synchronized(X.class)używa instancji klasy jako monitora. Ponieważ istnieje tylko jedna instancja klasy (obiekt reprezentujący metadane klasy w czasie wykonywania), w tym bloku może znajdować się jeden wątek.

Z synchronized(this)bloku jest chroniony przez instancję. W każdym przypadku tylko jeden wątek może wejść do bloku.

synchronized(X.class)służy do upewnienia się, że w bloku znajduje się dokładnie jeden wątek. synchronized(this)zapewnia, że ​​na instancję przypada dokładnie jeden wątek. Jeśli to sprawia, że ​​rzeczywisty kod w bloku jest bezpieczny dla wątków, zależy od implementacji. Jeśli mutate wystarczy tylko stan instancji synchronized(this).

Thomas Jung
źródło
6
„tyle wątków może wejść do bloku, ile jest wystąpień” oznacza, że ​​druga forma działa jak semafor, co nie jest prawdą. Powinieneś powiedzieć coś w stylu: „zsynchronizowany (to) zapewnia, że ​​tylko jeden wątek może wejść do bloku dla danej instancji klasy”.
liwp
Poprawione. Chciałem to powiedzieć.
Thomas Jung,
2
jaka jest instancja klasy w porównaniu z instancją?
Weishi Zeng
Tak więc, jeśli masz metodę statyczną i nie chcemy synchronizować całego jej ciała, to zsynchronizowaliśmy (to) nie jest dobre, zamiast tego zsynchronizowana (Foo.class) jest odpowiednia. Czy to prawda?
krupal.agile
84

Aby dodać do innych odpowiedzi:

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

jest równa

static synchronized void myMethod() {
  //code
}

i

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

jest równa

synchronized void myMethod() {
  //code
}
Jorn
źródło
12
Drugie czytanie zajęło mi stwierdzenie, że pierwsze dwa przykłady mają słowo kluczowe „statyczne”. Wystarczy wskazać to innym, którzy mogli to zobaczyć i przeoczyć. Bez słowa kluczowego static pierwsze dwa przykłady nie byłyby takie same.
kurtzbot
1
Te przykłady NIE są równoważne! Zsynchronizowane metody są „synchronizowane” jako dziura, gdy wątek próbuje wywołać metody. Z drugiej strony bloki mogą mieć kod nad i pod nimi, który może być wykonywany z wielu wątków. Synchronizują się tylko w obrębie bloku! To nie to samo!
JacksOnF1re
public static Singleton getInstance () {if (instance == null) {synchronized (Singleton.class) {instance = new Singleton (); }} zwracana instancja; }
JacksOnF1re
2
Istotą jest to, że nie ma żadnego kodu poza synchronizedblokami. To czyni je równoważnymi. Jeśli zmienisz jeden przykład, rzeczywiście nie są już takie same.
Jorn
23

Nie, pierwsza spowoduje zablokowanie definicji klasy MyClass, a nie wszystkich jej instancji. Jeśli jednak zostanie użyty w instancji, skutecznie zablokuje wszystkie inne instancje, ponieważ mają one wspólną definicję klasy.

Drugi blokuje tylko bieżącą instancję.

Czy to sprawia, że ​​twoje obiekty są bezpieczne, jest to znacznie bardziej złożone pytanie - musielibyśmy zobaczyć twój kod!

David M.
źródło
1
tak, MyClass.class może być dowolną zmienną statyczną i mieć ten sam efekt.
pstanton
0

Tak, będzie (na każdym zsynchronizowanym bloku / funkcji).

Nad tym pytaniem zastanawiałem się dla siebie przez kilka dni (właściwie w Kotlinie). W końcu znalazłem dobre wyjaśnienie i chcę się nim podzielić:

Blokada na poziomie klasy zapobiega wchodzeniu wielu wątków w zsynchronizowanym bloku we wszystkich dostępnych wystąpieniach klasy w czasie wykonywania. Oznacza to, że jeśli w czasie wykonywania jest 100 wystąpień DemoClass, tylko jeden wątek będzie mógł wykonać demoMethod () w dowolnej instancji na raz, a wszystkie inne wystąpienia zostaną zablokowane dla innych wątków.

Blokowanie na poziomie klasy powinno być zawsze wykonywane, aby zapewnić bezpieczeństwo wątków danych statycznych. Ponieważ wiemy, że statyczne słowo kluczowe kojarzy dane metod z poziomem klasy, użyj blokowania w statycznych polach lub metodach, aby zrobić to na poziomie klasy.

Dodatkowo warto zauważyć, dlaczego .class . Dzieje się tak dlatego, że .classjest odpowiednikiem dowolnej zmiennej statycznej klasy podobnej do:

private final static Object lock = new Object();

gdzie nazwa zmiennej blokady to class, a typ to Class <T>

Czytaj więcej: https://howtodoinjava.com/java/multi-threading/object-vs-class-level-locking/

vitalii
źródło