Sobes.tech
Middle

Proč je dochází k závodům vláken a jaké způsoby jejich boje existují?

sobes.tech AI

Odpověď od AI

Race conditions (závodní podmínky) nastávají, když několik vláken současně přistupuje ke sdíleným měnitelným datům a výsledek závisí na pořadí jejich provádění. K tomu dochází, protože operační systém může kdykoli přepínat vlákna, přerušujíc jejich běh.

Způsoby boje:

  • Synchronizace: Použití synchronizačních primitivů k zajištění exkluzivního přístupu ke sdíleným zdrojům.

    • synchronized klíčové slovo: Používá se na metody nebo bloky kódu. Zablokuje přístup k objektu nebo třídě ostatním vláknům, dokud aktuální vlákno nedokončí provádění synchronizovaného bloku/metody.

      // Synchronizovaná metoda
      public synchronized void updateData(int newValue) {
          // ... aktualizace sdílených dat
      }
      
      // Synchronizovaný blok kódu
      public void processData() {
          synchronized (this) { // Nebo jiný monitorovací objekt
              // ... přístup ke sdíleným datům
          }
      }
      
    • Zámky (Lock): Poskytují flexibilnější kontrolu nad synchronizací ve srovnání 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ískání zámku
          try {
              // ... aktualizace sdílených dat
          } finally {
              dataLock.unlock(); // Uvolnění zámku
          }
      }
      
  • Atomické proměnné (Atomic...): Poskytují vlákny bezpečné operace nad primitivními typy bez explicitního zámku. Používají se pro jednoduché operace (inkrementace, porovnání a výměna).

    import java.util.concurrent.atomic.AtomicInteger;
    
    private final AtomicInteger counter = new AtomicInteger(0);
    
    public void incrementCounter() {
        counter.incrementAndGet(); // Atomické zvýšení
    }
    
  • Vlákny bezpečné kolekce: Použití speciálních kolekcí z balíčku java.util.concurrent (například ConcurrentHashMap, CopyOnWriteArrayList), které jsou navrženy pro vícevláknový přístup.

    import java.util.concurrent.ConcurrentHashMap;
    import java.util.Map;
    
    private final Map<String, Integer> safeMap = new ConcurrentHashMap<>();
    
  • Neměnné (Immutable) objekty: Pokud se data po vytvoření nemění, lze k nim bezpečně přistupovat z více vláken bez synchronizace.

  • Lokální proměnné vlákna (ThreadLocal): Každému vláknu je přiřazena jeho kopie proměnné, což vylučuje konkurenci při přístupu.

    private final ThreadLocal<Integer> threadId = new ThreadLocal<>();
    
    public void setThreadId() {
        threadId.set(Thread.currentThread().getId());
    }
    
    public int getThreadId() {
        return threadId.get();
    }
    
  • Správný návrh architektury: Minimalizace sdílených měnitelných dat a použití asynchronních přístupů nebo předávání zpráv mezi vlákny může snížit pravděpodobnost vzniku závodů.