Sobes.tech
Middle

Ako synchronizovať interakciu medzi vláknami?

sobes.tech AI

Odpoveď od AI

Existuje niekoľko základných mechanizmov synchronizácie vlákien v C++:

  • Mutexy: Zabezpečujú vzájomné vylúčenie. Len jedno vlákno môže vlastniť mutex v danom okamihu. Používajú sa na ochranu spoločných zdrojov pred súčasným prístupom.

    #include <mutex>
    
    std::mutex myMutex;
    
    void criticalSection() {
        std::lock_guard<std::mutex> lock(myMutex); // Zámok mutexu
        // Práca so spoločným zdrojom
    } // Mutex sa automaticky uvoľní pri opustení rozsahu
    
  • Semafory: Riadi prístup k obmedzenému počtu zdrojov. Semafor má čítač, ktorý ukazuje počet dostupných zdrojov. Vlákna znižujú (získanie zdroja) a zvyšujú (uvoľnenie zdroja) tento čítač.

    #include <semaphore.h> // Bežne sa používa v POSIX systémoch
    
    sem_t mySemaphore;
    
    void initSemaphore(int count) {
        sem_init(&mySemaphore, 0, count); // Inicializácia semaforu s čítačom count
    }
    
    void acquireResource() {
        sem_wait(&mySemaphore); // Zníženie čítača, blokovanie pri 0
        // Použitie zdroja
    }
    
    void releaseResource() {
        sem_post(&mySemaphore); // Zvýšenie čítača
    }
    
  • Podmienkové premenné: Umožňujú vláknam čakať na určitý stav. Obvykle sa používajú spolu s mutexmi. Vlákno čakajúce na podmienku uvoľní mutex a zablokuje sa, kým ho iné vlákno ne upozorní na splnenie podmienky.

    #include <condition_variable>
    #include <mutex>
    #include <queue>
    
    std::condition_variable myCondition;
    std::mutex myMutex;
    std::queue<int> myQueue;
    
    void producer(int value) {
        std::lock_guard<std::mutex> lock(myMutex);
        myQueue.push(value);
        myCondition.notify_one(); // Upozornenie na jedno čakajúce vlákno
    }
    
    int consumer() {
        std::unique_lock<std::mutex> lock(myMutex);
        myCondition.wait(lock, [&]{ return !myQueue.empty(); }); // Čakanie na podmienku
        int value = myQueue.front();
        myQueue.pop();
        return value;
    }
    
  • Atomické premenné: Umožňujú vykonávať jednoduché operácie (čítanie, zápis, modifikácia) atomicky, bez potreby použitia mutexov pre tieto operácie.

    #include <atomic>
    
    std::atomic_int atomicCounter(0);
    
    void incrementCounter() {
        atomicCounter++; // Atomické zvýšenie
    }
    
  • Barriéry: Synchronizujú niekoľko vlákien tak, aby žiadne nemohlo pokračovať vo vykonávaní, kým všetky nedosiahnu bariéru.

    #include <barrier> // C++20
    
    std::barrier myBarrier(3); // Bariéra pre 3 vlákna
    
    void workerThread() {
        // Vykonanie časti práce
        myBarrier.arrive_and_wait(); // Čakanie na všetky vlákna na bariére
        // Vykonanie ďalšej časti práce
    }
    

Výber konkrétneho mechanizmu závisí od charakteru interakcie medzi vláknami:

  • Mutexy: Najbežnejší spôsob ochrany spoločných dát.
  • Semafory: Riadenie prístupu k obmedzeným zdrojom.
  • Podmienkové premenné: Čakanie vlákna na určitú udalosť alebo stav.
  • Atomické premenné: Efektívne vykonávanie jednoduchých, atomických operácií.
  • Barriéry: Synchronizácia vlákien pre spoločný prechod na ďalší krok.