Sobes.tech
Middle

Wie kann man die Interaktion zwischen Threads synchronisieren?

sobes.tech KI

Antwort von AI

Es gibt mehrere Hauptmechanismen zur Thread-Synchronisation in C++:

  • Mutexe: Gewährleisten gegenseitigen Ausschluss. Nur ein Thread kann zu einem Zeitpunkt ein Mutex besitzen. Werden verwendet, um gemeinsame Ressourcen vor gleichzeitigen Zugriffen zu schützen.

    #include <mutex>
    
    std::mutex myMutex;
    
    void criticalSection() {
        std::lock_guard<std::mutex> lock(myMutex); // Mutex erwerben
        // Arbeit mit gemeinsamem Ressourcen
    } // Mutex wird beim Verlassen des Gültigkeitsbereichs automatisch freigegeben
    
  • Semaphoren: Steuern den Zugriff auf begrenzte Ressourcen. Ein Semaphor hat einen Zähler, der die verfügbaren Ressourcen angibt. Threads können den Zähler verringern (um eine Ressource zu erhalten) oder erhöhen (um sie freizugeben).

    #include <semaphore.h> // Wird meist in POSIX-Systemen verwendet
    
    sem_t mySemaphore;
    
    void initSemaphore(int count) {
        sem_init(&mySemaphore, 0, count); // Initialisierung des Semaphors mit Zähler count
    }
    
    void acquireResource() {
        sem_wait(&mySemaphore); // Zähler verringern, blockieren bei 0
        // Ressource verwenden
    }
    
    void releaseResource() {
        sem_post(&mySemaphore); // Zähler erhöhen
    }
    
  • Bedingungsvariablen: Ermöglichen es Threads, auf eine bestimmte Bedingung zu warten. Werden meist zusammen mit Mutexen verwendet. Ein wartender Thread gibt den Mutex frei und wird blockiert, bis ein anderer Thread ihn über die Erfüllung der Bedingung benachrichtigt.

    #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(); // Benachrichtigung eines wartenden Threads
    }
    
    int consumer() {
        std::unique_lock<std::mutex> lock(myMutex);
        myCondition.wait(lock, [&]{ return !myQueue.empty(); }); // Warten auf Bedingung
        int value = myQueue.front();
        myQueue.pop();
        return value;
    }
    
  • Atomare Variablen: Ermöglichen die Ausführung einfacher Operationen (Lesen, Schreiben, Modifizieren) atomar, ohne Mutexes für diese spezifischen Operationen.

    #include <atomic>
    
    std::atomic_int atomicCounter(0);
    
    void incrementCounter() {
        atomicCounter++; // Atomare Erhöhung
    }
    
  • Barrieren: Synchronisieren mehrere Threads, sodass keiner fortfahren kann, bis alle die Barriere erreicht haben.

    #include <barrier> // C++20
    
    std::barrier myBarrier(3); // Barriere für 3 Threads
    
    void workerThread() {
        // Ausführung eines Teils der Arbeit
        myBarrier.arrive_and_wait(); // Warten, bis alle die Barriere erreicht haben
        // Ausführung des nächsten Arbeitsschritts
    }
    

Die Wahl eines bestimmten Mechanismus hängt von der Art der Interaktion zwischen den Threads ab:

  • Mutexe: Der am häufigsten verwendete Schutzmechanismus für gemeinsame Daten.
  • Semaphoren: Verwaltung des Zugriffs auf begrenzte Ressourcen.
  • Bedingungsvariablen: Warten auf ein Ereignis oder einen Zustand.
  • Atomare Variablen: Effiziente Ausführung einfacher, atomarer Operationen.
  • Barrieren: Synchronisation der Threads für den gemeinsamen Übergang zum nächsten Schritt.