Sobes.tech
Middle

Prečo vznikajú závody vlákien a aké spôsoby ich boja existujú?

sobes.tech AI

Odpoveď od AI

Podmienky pretečenia (race conditions) vznikajú, keď niekoľko vlákien súčasne pristupuje k spoločným meniteľným údajom a výsledok vykonávania závisí od poradia ich vykonávania. To sa deje, pretože operačný systém môže kedykoľvek prepínať vlákna, prerušujúc ich vykonávanie.

Spôsoby boja:

  • Synchronizácia: Použitie primitivov synchronizácie na zabezpečenie výlučného prístupu ku spoločným zdrojom.

    • synchronized kľúčové slovo: Používa sa na metódy alebo bloky kódu. Zablokuje prístup k objektu alebo triede pre iné vlákna, kým aktuálne vlákno nedokončí vykonávanie synchronizovaného bloku/metódy.

      // Synchronizovaná metóda
      public synchronized void updateData(int newValue) {
          // ... aktualizácia spoločných údajov
      }
      
      // Synchronizovaný blok kódu
      public void processData() {
          synchronized (this) { // Alebo iný monitorovací objekt
              // ... prístup ku spoločným údajom
          }
      }
      
    • Zámky (Lock): Poskytujú flexibilnejšiu kontrolu nad synchronizáciou v porovnaní s 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(); // Získanie zámku
          try {
              // ... aktualizácia spoločných údajov
          } finally {
              dataLock.unlock(); // Uvoľnenie zámku
          }
      }
      
  • Atómové premenné (Atomic...): Poskytujú vlákna bezpečné operácie nad primitívnymi typmi bez explicitného zámku. Používajú sa pre jednoduché operácie (inkrement, porovnanie a výmena).

    import java.util.concurrent.atomic.AtomicInteger;
    
    private final AtomicInteger counter = new AtomicInteger(0);
    
    public void incrementCounter() {
        counter.incrementAndGet(); // Atómické zvýšenie
    }
    
  • Vlákna bezpečné kolekcie: Použitie špeciálnych kolekcií z balíčka java.util.concurrent (napríklad ConcurrentHashMap, CopyOnWriteArrayList), ktoré sú navrhnuté pre viacvláknový prístup.

    import java.util.concurrent.ConcurrentHashMap;
    import java.util.Map;
    
    private final Map<String, Integer> safeMap = new ConcurrentHashMap<>();
    
  • Nemenné (Immutable) objekty: Ak sa údaje nemenia po vytvorení, je možné k nim bezpečne pristupovať z viacerých vlákien bez synchronizácie.

  • Lokálne premenné vlákna (ThreadLocal): Každému vláknu je pridelená jeho vlastná kópia premennej, čím sa vylučuje konkurencia za prístup.

    private final ThreadLocal<Integer> threadId = new ThreadLocal<>();
    
    public void setThreadId() {
        threadId.set(Thread.currentThread().getId());
    }
    
    public int getThreadId() {
        return threadId.get();
    }
    
  • Správne navrhnutie architektúry: Minimalizácia spoločných meniteľných údajov a použitie asynchrónnych prístupov alebo odovzdávania správ medzi vláknami môže znížiť pravdepodobnosť výskytu závodov.