Sobes.tech
Middle

Hogyan lehet szinkronizálni a szálak közötti interakciót?

sobes.tech MI

Válasz az MI-től

A C++-ban több alapvető szál-szinkronizációs mechanizmus létezik:

  • Mutexek: Kölcsönös kizárást biztosítanak. Csak egy szál lehet egyszerre a mutex tulajdonosa. Általában a közös erőforrások védelmére használják.

    #include <mutex>
    
    std::mutex myMutex;
    
    void criticalSection() {
        std::lock_guard<std::mutex> lock(myMutex); // Mutex megszerzése
        // Közös erőforrással való munka
    } // A mutex automatikusan felszabadul, amikor kilép a láthatósági körből
    
  • Szelep (Semaphores): Korlátozott erőforrásokhoz való hozzáférést kezelnek. A semaphore számlálója megmutatja az elérhető erőforrások számát. A szálak csökkentik (erőforrás megszerzése) és növelik (erőforrás felszabadítása) a számlálót.

    #include <semaphore.h> // Általában POSIX rendszereken használják
    
    sem_t mySemaphore;
    
    void initSemaphore(int count) {
        sem_init(&mySemaphore, 0, count); // Semaphore inicializálása a count értékkel
    }
    
    void acquireResource() {
        sem_wait(&mySemaphore); // Számláló csökkentése, blokkol, ha 0
        // Erőforrás használata
    }
    
    void releaseResource() {
        sem_post(&mySemaphore); // Számláló növelése
    }
    
  • Feltétel változók (Condition Variables): Lehetővé teszik a szálak számára, hogy bizonyos feltételre várjanak. Általában mutexekkel együtt használják. A feltételt váró szál felszabadítja a mutexet és blokkolódik, amíg egy másik szál nem értesíti, hogy a feltétel teljesült.

    #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(); // Egy várakozó szál értesítése
    }
    
    int consumer() {
        std::unique_lock<std::mutex> lock(myMutex);
        myCondition.wait(lock, [&]{ return !myQueue.empty(); }); // Feltétel várása
        int value = myQueue.front();
        myQueue.pop();
        return value;
    }
    
  • Atomi változók (Atomic Variables): Lehetővé teszik egyszerű műveletek (olvasás, írás, módosítás) atomikus végrehajtását, mutex használata nélkül.

    #include <atomic>
    
    std::atomic_int atomicCounter(0);
    
    void incrementCounter() {
        atomicCounter++; // Atomikus növelés
    }
    
  • Barrier-ek: Szinkronizálják több szálat úgy, hogy egyik sem folytathatja a végrehajtást, amíg mindegyik el nem éri a barrier-t.

    #include <barrier> // C++20
    
    std::barrier myBarrier(3); // 3 szálra
    
    void workerThread() {
        // Munka egy része
        myBarrier.arrive_and_wait(); // Várakozás minden szálra a barrier-nél
        // Következő munka rész
    }
    

A konkrét mechanizmus kiválasztása a szálak közötti kölcsönhatás jellegétől függ:

  • Mutexek: A leggyakoribb módszer a közös adatok védelmére.
  • Szelep (Semaphores): A hozzáférés korlátozott erőforrásokhoz való kezelés.
  • Feltétel változók: A szálak várakozása egy adott esemény vagy állapot bekövetkeztére.
  • Atomi változók: Hatékony végrehajtása egyszerű, atomikus műveleteknek.
  • Barrier-ek: Szálak szinkronizálása a következő szakaszhoz való közös átmenethez.