Sobes.tech
Middle

Kokie yra pagrindiniai sinchronizacijos būdai Java?

sobes.tech AI

Atsakymas iš AI

Pagrindiniai sinchronizacijos būdai Java:

  1. synchronized raktinis žodis:

    • Naudojamas metodų arba kodo blokų sinchronizavimui.
    • synchronized žymėtas metodas blokuoja prieigą prie objekto instancijos kitiems sinchronizuotiems to paties objekto metodams.
    • synchronized (this): sinchronizacija pagal esamą objekto instanciją.
    • synchronized (ClassName.class): sinchronizacija pagal klasę, blokuoja prieigą visiems srautams, dirbantiems su šiuo klasiu.
    • synchronized (object): sinchronizacija pagal konkretų monitoriaus objektą.
    class Counter {
        private int count = 0;
    
        // Sinchronizuotas metodas
        public synchronized void increment() {
            count++;
        }
    
        public void decrement() {
            // Sinchronizuotas blokas
            synchronized (this) {
                count--;
            }
        }
    }
    
  2. volatile raktinis žodis:

    • Garantuoja kintamojo matomumą tarp srautų.
    • Neužtikrina sudėtingų operacijų atomingumo (pvz., i++), tik skaitymą ir rašymą.
    • Taikomas klasės laukams.
    class SharedData {
        volatile boolean flag = false;
    
        public void setFlag(boolean value) {
            flag = value; // Flag keitimas tampa matomas kitiems srautams
        }
    
        public boolean getFlag() {
            return flag;
        }
    }
    
  3. Išorinės užrakinimo priemonės (Explicit Locks):

    • Siūlo lankstesnę kontrolę nei synchronized.
    • Lock sąsaja ir jos įgyvendinimai, pvz., ReentrantLock.
    • Leidžia pasirinkti sąžiningą ir nesąžiningą užrakinimo režimą, gauti užrakinimo būseną, nutraukti srautą užrakinimo metu.
    • Reikalauja aiškaus lock() ir unlock() iškvietimo. Svarbu naudoti finally bloką unlock() iškvietimui.
    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(); // Užrakinimo gavimas
            try {
                // Kritinė sekcija
                System.out.println(Thread.currentThread().getName() + " užėmė užraktą");
                Thread.sleep(100); // Darbo imitacija
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                lock.unlock(); // Užrakinimo atlaisvinimas
                System.out.println(Thread.currentThread().getName() + " atlaisvino užraktą");
            }
        }
    }
    
  4. wait(), notify(), notifyAll():

    • Object klasės metodai, naudojami srautų sąveikai, laukiančioms monitoriaus atlaisvinimo.
    • wait(): atlaisvina monitorių ir perveda srautą į laukimo būseną iki notify() ar notifyAll() iškvietimo.
    • notify(): pažadina vieną laukiančią srautą.
    • notifyAll(): pažadina visus laukiančius srautus.
    • Juos reikia iškviesti to paties monitoriaus sinchronizuotame bloke ar metode.
    class ProducerConsumer {
        private final Object monitor = new Object();
        private boolean isProduced = false;
    
        public void produce() throws InterruptedException {
            synchronized (monitor) {
                while (isProduced) {
                    monitor.wait(); // Laukia, kol vartotojas suvalgys
                }
                // Gamina
                System.out.println("Gamyba");
                isProduced = true;
                monitor.notifyAll(); // Praneša vartotojams
            }
        }
    
        public void consume() throws InterruptedException {
            synchronized (monitor) {
                while (!isProduced) {
                    monitor.wait(); // Laukia, kol gamintojas pagamins
                }
                // Vartoja
                System.out.println("Vartoja");
                isProduced = false;
                monitor.notifyAll(); // Praneša gamintojams
            }
        }
    }
    

Šie mechanizmai yra pagrindas kurti saugų daugiagijų kodą Java. Pasirinkimas priklauso nuo užduoties ypatybių ir reikiamos kontrolės lygio.