Sobes.tech
Middle

Реци о стању трке (race condition) и како га избегнути у мулти-тред апликацијама.

sobes.tech АИ

Одговор од АИ

Stanje trke je greška u dizajnu višedretvenog sistema, pri čemu rezultat izvršavanja programa zavisi od reda izvršavanja delova koda od strane različitih niti. To se dešava kada više niti istovremeno pristupa zajedničkom promenljivom resursu bez odgovarajuće sinhronizacije.

Da bi se izbeglo stanje trke u Javi, koriste se sledeći pristupi:

  1. Upotreba sinhronizovanih metoda i blokova:

    class Counter {
        private int count = 0;
    
        // Sinhronizovana metoda
        public synchronized void increment() {
            count++;
        }
    
        // Sinhronizovani blok
        public void decrement() {
            synchronized (this) {
                count--;
            }
        }
    }
    

    Ključna reč synchronized garantuje da samo jedna nit u isto vreme može izvršavati sinhronizovani kod za taj objekat (ili za klasu, ako je metoda statična).

  2. Upotreba klase Lock iz paketa java.util.concurrent.locks:

    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    class SafeCounter {
        private int count = 0;
        private final Lock lock = new ReentrantLock();
    
        public void increment() {
            lock.lock(); // Zauzimanje blokade
            try {
                count++;
            } finally {
                lock.unlock(); // Oslobađanje blokade
            }
        }
    }
    

    Lock pruža fleksibilnije mehanizme zaključavanja u poređenju sa synchronized.

  3. Upotreba atomskih promenljivih iz paketa java.util.concurrent.atomic:

    import java.util.concurrent.atomic.AtomicInteger;
    
    class AtomicCounter {
        private AtomicInteger count = new AtomicInteger(0);
    
        public void increment() {
            count.incrementAndGet(); // Atomarska operacija
        }
    }
    

    Atomarske promenljive pružaju atomarske operacije (npr. inkrement, dekrement) koje se izvršavaju kao celina i ne mogu biti prekinute drugim nitima.

  4. Upotreba niti-bezbednih kolekcija iz paketa java.util.concurrent: Na primer, ConcurrentHashMap, CopyOnWriteArrayList. Ove kolekcije su dizajnirane za sigurnu upotrebu u višedretvenom okruženju.

  5. Izbegavanje zajedničkog promenljivog stanja: Ako je moguće, podaci kojima pristupaju više niti treba da budu nepromenljivi (immutable) ili da budu odvojeni za svaku nit.

  6. Upotreba volatile: Ključna reč volatile garantuje vidljivost promena promenljive za sve niti, ali ne obezbeđuje atomarnost operacija (osim čitanja i pisanja primitivnih tipova, osim long i double, i referenci). Korisno je u kombinaciji sa drugim mehanizmima ili za jednostavne, nezavisne operacije stanja.

    class VolatileFlag {
        volatile boolean flag = false; // Garantovana vidljivost promena
    
        public void setFlag() {
            flag = true;
        }
    
        public boolean isFlag() {
            return flag;
        }
    }
    

Izbor odgovarajuće metode zavisi od konkretne situacije i zahteva za performanse i složenost koda.