Sobes.tech
Middle

Milyen alapvető szinkronizációs módszerek vannak Java-ban?

sobes.tech MI

Válasz az MI-től

A Java alapvető szinkronizációs módszerei:

  1. A synchronized kulcsszó:

    • Olyan módszerek vagy kódblokkok szinkronizálására használják.
    • A synchronized-nel jelölt módszer blokkolja a hozzáférést az objektum példányához más szinkronizált módszerek számára ugyanazon az objektumon.
    • synchronized (this): szinkronizálás a jelenlegi példányon.
    • synchronized (ClassName.class): szinkronizálás a osztályon, blokkolva minden szál hozzáférését ehhez az osztályhoz.
    • synchronized (object): szinkronizálás egy adott monitor objektumon.
    class Counter {
        private int count = 0;
    
        // Szinkronizált metódus
        public synchronized void increment() {
            count++;
        }
    
        public void decrement() {
            // Szinkronizált blokk
            synchronized (this) {
                count--;
            }
        }
    }
    
  2. A volatile kulcsszó:

    • Biztosítja a változó változásainak láthatóságát a szálak között.
    • Nem garantálja összetett műveletek atomaritását (pl. i++), csak olvasást és írást.
    • Osztálymezőkre alkalmazható.
    class SharedData {
        volatile boolean flag = false;
    
        public void setFlag(boolean value) {
            flag = value; // A flag változása látható lesz más szálak számára
        }
    
        public boolean getFlag() {
            return flag;
        }
    }
    
  3. Explicit Lockok (Kifejezett zárolások):

    • Rugalmasabb kontrollt biztosítanak a synchronized-hez képest.
    • A Lock interfész és annak implementációi, például a ReentrantLock.
    • Lehetővé teszik a tisztességes és tisztességtelen zárolási módok közötti választást, a zárolási állapot lekérdezését, a szál megszakítását zárolási várakozás közben.
    • Egyértelmű lock() és unlock() hívásokat igényelnek. Fontos a finally blokkban hívni az unlock()-ot.
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    class Resource {
        private final Lock lock = new ReentrantLock();
    
        public void performAction() {
            lock.lock(); // Zárolás megszerzése
            try {
                // Kritikus szakasz
                System.out.println(Thread.currentThread().getName() + " zárolt");
                Thread.sleep(100); // Munka szimulálása
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                lock.unlock(); // Zárolás feloldása
                System.out.println(Thread.currentThread().getName() + " feloldotta a zárolást");
            }
        }
    }
    
  4. wait(), notify(), notifyAll():

    • Az Object osztály metódusai, amelyek a szálak közötti interakcióra szolgálnak, várva a monitor felszabadítására.
    • wait(): felszabadítja a monitort és várakozó állapotba helyezi a szálat, amíg notify() vagy notifyAll() nem hívódik.
    • notify(): felébreszt egy várakozó szálat ezen a monitoron.
    • notifyAll(): felébreszti az összes várakozó szálat ezen a monitoron.
    • Ugyanazon monitor objektumon belül kell hívni őket, szinkronizált blokk vagy metódus részeként.
    class ProducerConsumer {
        private final Object monitor = new Object();
        private boolean isProduced = false;
    
        public void produce() throws InterruptedException {
            synchronized (monitor) {
                while (isProduced) {
                    monitor.wait(); // Várakozás, amíg a fogyasztó elfogyasztja
                }
                // Gyártás
                System.out.println("Gyártott");
                isProduced = true;
                monitor.notifyAll(); // Fogyasztók értesítése
            }
        }
    
        public void consume() throws InterruptedException {
            synchronized (monitor) {
                while (!isProduced) {
                    monitor.wait(); // Várakozás, amíg a gyártó gyárt
                }
                // Fogyasztás
                System.out.println("Fogyasztott");
                isProduced = false;
                monitor.notifyAll(); // Gyártók értesítése
            }
        }
    }
    

Ezek a mechanizmusok alapvetőek a biztonságos több szálú kód létrehozásához Java-ban. A konkrét módszer kiválasztása a feladat jellemzőitől és a szinkronizáció feletti kontroll szintjétől függ.