Middle
Čo je blok synchronized v Jave a aké problémy môžu pri jeho používaní nastať?
sobes.tech AI
Odpoveď od AI
Blok synchronized v Jave sa slúži na zabezpečenie synchronizácie prístupu ku spoločnému zdroju medzi viacerými vláknami. To zaručuje, že iba jedno vlákno môže vykonávať kód vo vnútri bloku v danom čase.
Struktúra bloku synchronized:
synchronized (monitorovy_objekt) {
// Kritická sekcia
// Tu sa vykonávajú operácie so spoločným zdrojom
}
monitorovy_objekt: akýkoľvek objekt, ktorý slúži ako monitor (zámok). Vlákna, ktoré sa pokúsia vstúpiť dosynchronizedbloku s rovnakým objektom, budú zablokované, kým aktuálne vlákno ne opustí blok.
Problémy, ktoré môžu nastať pri používaní synchronized:
- Vražedný zámok (Deadlock): Dve alebo viac vlákien čakajú na uvoľnenie zdroja, ktorý je obsadený iným vláknom, čo vedie k zablokovaniu programu. To sa môže stať, ak vlákna získavajú zámky v rôznom poradí.
- Zníženie výkonu: Synchronizácia blokuje vykonávanie iných vlákien, ktoré čakajú na prístup k monitoru, čo môže spomaliť prácu paralelných aplikácií.
- Neaplikovateľnosť v niektorých scenároch:
synchronizedzabezpečuje exkluzívny prístup. V niektorých prípadoch môže byť potrebné flexibilnejšie riadenie prístupu (napríklad čítanie viacerými vláknami súčasne, zápis v jednom vlákne). - Zložitosť ladenia: Problémy so synchronizáciou môžu byť nejasné a ťažko reprodukovateľné a odhaľovateľné.
Príklad vzájomného zámku:
class Resource {
private Object lock1 = new Object();
private Object lock2 = new Object();
public void method1(Resource other) {
synchronized (lock1) {
try {
Thread.sleep(100); // Simulácia práce
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " získal lock1");
synchronized (other.lock2) {
System.out.println(Thread.currentThread().getName() + " získal lock2 iného");
}
}
}
public void method2(Resource other) {
synchronized (lock2) {
try {
Thread.sleep(100); // Simulácia práce
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " získal lock2");
synchronized (other.lock1) {
System.out.println(Thread.currentThread().getName() + " získal lock1 iného");
}
}
}
}
public class DeadlockExample {
public static void main(String[] args) {
Resource r1 = new Resource();
Resource r2 = new Resource();
new Thread(() -> r1.method1(r2), "Thread-1").start();
new Thread(() -> r2.method2(r1), "Thread-2").start();
}
}
V tomto príklade sa Thread-1 snaží získať lock1 r1 a potom lock2 r2. Thread-2 sa snaží získať lock2 r2 a potom lock1 r1. Ak ich získajú súčasne, dôjde k vzájomnému zámku.