Sobes.tech
Middle

Kokius būdus žinote, kaip kovoti su gijų lenktynėmis, išskyrus volatile raktažodžio naudojimą?

sobes.tech AI

Atsakymas iš AI

Yra keletas pagrindinių būdų sinchronizuoti srautus ir išvengti lenktynių sąlygų Android platformoje, be volatile.

  1. Naudojant synchronized: Blokuoja prieigą prie kodo ar metodo kitiems srautams iki kol baigsis esamas srautas.

    // Sinchronizuotas metodas
    synchronized void incrementCounter() {
        counter++;
    }
    
    // Sinchronizuotas blokas
    void updateData() {
        synchronized (this) { // arba kitas monitoriaus objektas
            // kodas, reikalaujantis sinchronizacijos
        }
    }
    
  2. Naudojant java.util.concurrent.locks paketą: Siūlo lankstesnius užrakinimo mechanizmus nei synchronized.

    import java.util.concurrent.locks.ReentrantLock;
    
    private final ReentrantLock lock = new ReentrantLock();
    
    void performLockedOperation() {
        lock.lock(); // Užrakinimo gavimas
        try {
            // kodas, apsaugotas užrakinimu
        } finally {
            lock.unlock(); // Užrakinimo atlaisvinimas
        }
    }
    
  3. Naudojant java.util.concurrent.atomic paketą: Siūlo atominius veiksmus, kurie vykdomi kaip vienetas be pertraukos kitų srautų.

    import java.util.concurrent.atomic.AtomicInteger;
    
    private final AtomicInteger atomicCounter = new AtomicInteger(0);
    
    void incrementAtomicCounter() {
        atomicCounter.incrementAndGet(); // Atominis didinimas
    }
    
  4. Naudojant saugias kolekcijas: Kolekcijos iš java.util.concurrent paketo, tokios kaip ConcurrentHashMap, CopyOnWriteArrayList, yra sukurtos saugiam naudojimui daugiasraityje aplinkoje be aiškios sinchronizacijos.

    import java.util.concurrent.ConcurrentHashMap;
    import java.util.Map;
    
    private final Map<String, Integer> concurrentMap = new ConcurrentHashMap<>();
    
    void updateMap(String key, Integer value) {
        concurrentMap.put(key, value); // saugi rašymo operacija
    }
    
  5. Naudojant ThreadLocal: Leidžia sukurti kintamąjį, kuris kiekvienam srautui turi atskirą kopiją. Taip kiekvienas srautas dirba su savo duomenimis, išvengiant lenktynių.

    private final ThreadLocal<Integer> threadLocalValue = new ThreadLocal<Integer>() {
        @Override
        protected Integer initialValue() {
            return 0; // pradinė reikšmė kiekvienam srautui
        }
    };
    
    void processData() {
        int value = threadLocalValue.get();
        value++;
        threadLocalValue.set(value); // nustatyti reikšmę esamam srautui
    }
    

Pasirinkimas priklauso nuo užduoties specifikos, užrakinimo poreikio, duomenų tipo ir reikalaujamo našumo.