Sobes.tech
Middle

Kodėl kyla sriečių lenktynės ir kaip su tuo kovoti?

sobes.tech AI

Atsakymas iš AI

Raitų sąlygos (race conditions) atsiranda, kai keli srautai vienu metu prieina prie bendrų kintamųjų duomenų, ir galutinis rezultatas priklauso nuo jų vykdymo tvarkos. Problema ta, kad srautų planuotojas gali bet kuriuo momentu perjungti srautą, ir duomenų operacija, kuri kodo atrodo kaip atominė, gali būti nutraukta ir įvykdyta dalimis kitų srautų.

Kovojant su srautų lenktynėmis, svarbu užtikrinti teisingą prieigą prie bendrų išteklių. Pagrindiniai metodai:

  • Sinchronizacija: riboja vienu metu prieigą prie kritinių kodo sekcijų, kur naudojami bendri duomenys. Populiarūs mechanizmai:

    • synchronized raktažodis: užtikrina užraktą objekto arba klasės lygyje.
    // Užraktas objekto lygyje
    synchronized (this) {
        // Kritinė sekcija
        sharedData++;
    }
    
    // Užraktas klasės lygyje
    synchronized (MyClass.class) {
        // Kritinė sekcija
        sharedStaticData++;
    }
    
    • Tiesioginiai užraktai (Lock sąsaja, ReentrantLock): suteikia daugiau lankstumo, pavyzdžiui, bandyti gauti užraktą arba gauti jį su laiko limitu.
    Lock lock = new ReentrantLock();
    // ...
    lock.lock(); // Gauti užraktą
    try {
        // Kritinė sekcija
        sharedData++;
    } finally {
        lock.unlock(); // Atlaisvinti užraktą (būtina finally)
    }
    
  • Atomarinės operacijos: naudojant java.util.concurrent.atomic paketo klases, kurios teikia atomines operacijas (pavyzdžiui, inkrementavimą, palyginimą ir keitimą) be aiškios užrakinimo.

    import java.util.concurrent.atomic.AtomicInteger;
    
    AtomicInteger atomicCounter = new AtomicInteger(0);
    // ...
    atomicCounter.incrementAndGet(); // Atomarinis padidinimas
    
  • Srauto saugios kolekcijos: naudojant java.util.concurrent paketo kolekcijas (pavyzdžiui, ConcurrentHashMap, CopyOnWriteArrayList), kurios yra sukurtos darbui daugiagijų aplinkoje.

  • Nepakitę duomenys (Immutable objects): jei duomenys po sukūrimo negali būti keičiami, daugkartinis prieiga prie jų nesukels lenktynių sąlygų.

  • Srauto vietinė saugykla (Thread-Local Storage): kiekvienas srautas turi savo kopiją, taip išsprendžiant bendro prieigos problemą.

Pasirinkimas priklauso nuo konkrečios situacijos ir reikalaujamo sinchronizacijos lygio. Per didelė sinchronizacija gali sukelti reikšmingų išlaidų ir net deadlock'ų.