Sobes.tech
Middle

Pasakykite apie lenktynių būseną (race condition) ir kaip jos galima išvengti daugialypėse programose.

sobes.tech AI

Atsakymas iš AI

Darbų būklė yra daugiagijinio sistemos projektavimo trūkumas, kai programos vykdymo rezultatas priklauso nuo to, kaip tvarkomi kodo dalys skirtingų sruogų. Tai įvyksta, kai keli sruogos vienu metu prieina prie bendro kintamojo ištekliaus be tinkamos sinchronizacijos.

Norint išvengti lenktynių būsenos Java, naudojami šie požiūriai:

  1. Naudojant sinchronizuotas metodus ir blokus:

    class Counter {
        private int count = 0;
    
        // Sinchronizuotas metodas
        public synchronized void increment() {
            count++;
        }
    
        // Sinchronizuotas blokas
        public void decrement() {
            synchronized (this) {
                count--;
            }
        }
    }
    

    Raktinis žodis synchronized užtikrina, kad tik viena sruoga vienu metu gali vykdyti sinchronizuotą kodą šiam objektui (arba klasei, jei metodas statinis).

  2. Naudojant Lock klasę iš java.util.concurrent.locks paketo:

    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(); // Užrakinimo įgijimas
            try {
                count++;
            } finally {
                lock.unlock(); // Atskleidimo
            }
        }
    }
    

    Lock suteikia lankstesnius užrakinimo mechanizmus nei synchronized.

  3. Naudojant atominius kintamuosius iš java.util.concurrent.atomic paketo:

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

    Atominiai kintamieji teikia atominius veiksmus (pvz., didinimą, mažinimą), kurie vykdomi kaip vienas vienetas ir negali būti nutraukti kitų sruogų.

  4. Naudojant saugias sruogų kolekcijas iš java.util.concurrent paketo: Pavyzdžiui, ConcurrentHashMap, CopyOnWriteArrayList. Šios kolekcijos sukurtos saugiam naudojimui daugiagijiniame aplinkoje.

  5. Vengiant bendro kintamojo būsenos: Jei įmanoma, duomenys, prieinami kelioms sruogoms, turėtų būti nekintami (immutable) arba atskiri kiekvienai sruogai.

  6. Naudojant volatile: Raktinis žodis volatile užtikrina, kad kintamojo pakeitimai būtų matomi visoms sruogoms, tačiau nesuteikia operacijų atomingumo (išskyrus paprastų primityvių tipų skaitymą ir rašymą, išskyrus long ir double, taip pat nuorodų). Tai naudinga kartu su kitais mechanizmais arba paprastoms, nepriklausomoms nuo būsenos operacijoms.

    class VolatileFlag {
        volatile boolean flag = false; // Pakeitimų matomumas garantuotas
    
        public void setFlag() {
            flag = true;
        }
    
        public boolean isFlag() {
            return flag;
        }
    }
    

Pasirinkimas priklauso nuo konkrečios situacijos ir našumo bei kodo sudėtingumo reikalavimų.