Sobes.tech
Middle

Zašto nastaju trke niti i koja rešenja postoje za njihovo suzbijanje?

sobes.tech АИ

Одговор од АИ

Utrke uslova (race conditions) nastaju kada više niti istovremeno pristupa zajedničkim promenljivim podacima, a rezultat izvršenja zavisi od reda njihovog izvršavanja. To se dešava zato što operativni sistem može prebacivati niti u bilo kom trenutku, prekidajući njihovo izvršenje.

Načini za borbu:

  • Sinhronizacija: Korišćenje primitiva za sinhronizaciju radi obezbeđivanja ekskluzivnog pristupa zajedničkim resursima.

    • synchronized ključna reč: Koristi se na metodama ili blokovima koda. Zaključava pristup objektu ili klasi za druge niti dok trenutna nit ne završi izvršenje sinhronizovanog bloka/metoda.

      // Sinhronizovana metoda
      public synchronized void updateData(int newValue) {
          // ... ažuriranje zajedničkih podataka
      }
      
      // Sinhronizovani blok koda
      public void processData() {
          synchronized (this) { // Ili drugi monitor objekat
              // ... pristup zajedničkim podacima
          }
      }
      
    • Zaključavanja (Lock): Omogućavaju fleksibilniji kontrolu nad sinhronizacijom u poređenju sa synchronized.

      import java.util.concurrent.locks.Lock;
      import java.util.concurrent.locks.ReentrantLock;
      
      private final Lock dataLock = new ReentrantLock();
      
      public void safeUpdateData(int newValue) {
          dataLock.lock(); // Zauzimanje zaključavanja
          try {
              // ... ažuriranje zajedničkih podataka
          } finally {
              dataLock.unlock(); // Oslobađanje zaključavanja
          }
      }
      
  • Atomične promenljive (Atomic...): Obezbeđuju operacije bezbedne za niti nad primitivnim tipovima bez eksplicitnog zaključavanja. Koriste se za jednostavne operacije (inkrement, poređenje i razmena).

    import java.util.concurrent.atomic.AtomicInteger;
    
    private final AtomicInteger counter = new AtomicInteger(0);
    
    public void incrementCounter() {
        counter.incrementAndGet(); // Atomično povećanje
    }
    
  • Niti-bezbedne kolekcije: Korišćenje specijalnih kolekcija iz paketa java.util.concurrent (npr., ConcurrentHashMap, CopyOnWriteArrayList), koje su dizajnirane za višestruki pristup nitima.

    import java.util.concurrent.ConcurrentHashMap;
    import java.util.Map;
    
    private final Map<String, Integer> safeMap = new ConcurrentHashMap<>();
    
  • Neizmenjivi (Immutable) objekti: Ako se podaci ne menjaju nakon kreiranja, njima se može sigurno pristupati iz više niti bez sinhronizacije.

  • Lokalne promenljive niti (ThreadLocal): Svakoj niti se dodeljuje sopstvena kopija promenljive, čime se isključuje konkurencija za pristup.

    private final ThreadLocal<Integer> threadId = new ThreadLocal<>();
    
    public void setThreadId() {
        threadId.set(Thread.currentThread().getId());
    }
    
    public int getThreadId() {
        return threadId.get();
    }
    
  • Pravilno projektovanje arhitekture: Minimiziranje zajednički promenljivih podataka i korišćenje asinhronih pristupa ili prenosa poruka između niti može smanjiti verovatnoću nastanka trkačkih uslova.