Synchronizacja odnosi się do wielowątkowości. Zsynchronizowany blok kodu może być wykonywany tylko przez jeden wątek na raz. Java obsługuje wiele wątków do wykonania. Może to spowodować, że dwa lub więcej wątków będzie miało dostęp do tego samego pola lub obiektu. Synchronizacja to proces, który umożliwia synchroniczne działanie wszystkich równoległych wątków w programie. Synchronizacja pozwala uniknąć błędów spójności pamięci spowodowanych niespójnym dostępem do pamięci współdzielonej. Kiedy metoda jest zadeklarowana jako zsynchronizowana, wątek przechowuje monitor obiektu, którego metoda jest wykonywana. Jeśli inny wątek wykonuje metodę zsynchronizowaną, Twój wątek zostanie zablokowany, dopóki inny wątek nie zwolni monitora. Synchronizację osiąga się w Javie za pomocą słowa zastrzeżonego
synchronized
. Możesz go używać na swoich zajęciach, definiując zsynchronizowane metody lub bloki. Nie będzie można używać synchronized
zmiennych ani atrybutów w definicji klasy.
Blokowanie na poziomie obiektu
Jest to mechanizm synchronizacji niestatycznej metody lub niestatycznego bloku kodu w taki sposób, że tylko jeden wątek może wykonać dany blok lub metodę w danej instancji klasy. Należy to zrobić za każdym razem, gdy trzeba zabezpieczyć wątek danych na poziomie instancji. Przykład:public class DemoClass{
public synchronized void demoMethod(){}
}
Lub
public class DemoClass{
public void demoMethod(){
synchronized (this) {
//other thread safe code
}
}
}
Lub
public class DemoClass{
private final Object lock = new Object();
public void demoMethod(){
synchronized (lock) {
//other thread safe code
}
}
}
Blokowanie na poziomie klasy
Zapobiega wejściu wielu wątków do zsynchronizowanego bloku podczas wykonywania w dowolnej z dostępnych instancji klasy. Oznacza to, że jeśli podczas wykonywania programu wystąpi 100 instancji klasyDemoClass
, to w tym momencie tylko jeden wątek będzie mógł wykonać się demoMethod()
w którymkolwiek z przypadków, a wszystkie pozostałe przypadki zostaną zablokowane dla pozostałych wątków. Jest to konieczne, gdy trzeba zabezpieczyć wątek danych statycznych.
public class DemoClass{
public synchronized static void demoMethod(){}
}
Lub
public class DemoClass{
public void demoMethod(){
synchronized (DemoClass.class) {
//other thread safe code
}
}
}
Lub
public class DemoClass
{
private final static Object lock = new Object();
public void demoMethod(){
synchronized (lock) {
//other thread safe code
}
}
}
Kilka ważnych uwag
- Synchronizacja w Javie gwarantuje, że żadne dwa wątki nie będą mogły wykonać zsynchronizowanej metody w tym samym czasie lub równolegle.
synchronized
można używać tylko z metodami i blokami kodu. Te metody lub bloki mogą być statyczne lub niestatyczne.- Za każdym razem, gdy jakikolwiek wątek wchodzi do zsynchronizowanej metody lub bloku, nabywa blokadę, a za każdym razem, gdy wątek opuszcza zsynchronizowaną metodę lub blok, JVM zwalnia blokadę. Blokada zostaje zwolniona, nawet jeśli wątek opuści metodę synchronized po zakończeniu z powodu błędów lub wyjątków.
synchronized
w Javie oznacza to , że jeśli metoda zsynchronizowana wywołuje inną metodę zsynchronizowaną, która wymaga tej samej blokady, bieżący wątek trzymający blokadę może wejść do tej metody bez uzyskania blokady.- Синхронизация в Java будет бросать
NullPointerException
если obiekt используемый в синхронизированном блоке null. Например, в вышеприведенном примере kodа, если замок инициализируется Jaknull
, синхронизированный (lock) броситNullPointerException
. - Синхронизированные методы в Java вносят дополнительные затраты на производительность вашего Aplikacje. Так что используйте синхронизацию, когда она абсолютно необходима. Кроме того, рассмотрите вопрос об использовании синхронизированных блоков kodа для синхронизации только критических секций kodа.
- Вполне возможно, что и статический и не статический синхронизированные методы могут работать одновременно Lub параллельно, потому что они захватывают замок на другой obiekt.
- В соответствии со спецификацией языка вы не можете использовать
synchronized
в конструкторе это приведет к ошибке компиляции. - Не синхронизируйте по не финальному (no final) полю, потому что połączyć, на не финальное поле может измениться в любое время, а затем другой поток может получить синхронизацию на разных obiektах и уже не будет ниJakой синхронизации вообще. Лучше всего использовать класс
String
, который уже неизменяемый и финальный.
GO TO FULL VERSION