Sobes.tech
Middle

Kaip galima sinchronizuoti tarpų sąveiką?

sobes.tech AI

Atsakymas iš AI

C++ yra keli pagrindiniai mechanizmai srautų sinchronizacijai:

  • MUTEX'ai (Mutexes): užtikrina išimtį. Tik vienas srautas gali turėti mutex'ą bet kuriuo metu. Naudojami bendriems ištekliams apsaugoti nuo vienalaikio prieigos.

    #include <mutex>
    
    std::mutex myMutex;
    
    void criticalSection() {
        std::lock_guard<std::mutex> lock(myMutex); // užfiksuoti mutex'ą
        // Darbas su bendru ištekliu
    } // mutex'as automatiškai atlaisvinamas išeinant iš apimties
    
  • Semaforai (Semaphores): valdo prieigą prie riboto kiekio išteklių. Semaforas turi skaitiklį, kuris nurodo prieinamų išteklių skaičių. Srautai mažina skaitiklį (gaudami išteklių) ir didina (atlaisvindami).

    #include <semaphore.h> // dažnai naudojama POSIX sistemose
    
    sem_t mySemaphore;
    
    void initSemaphore(int count) {
        sem_init(&mySemaphore, 0, count); // semaforo inicijavimas su skaitikliu count
    }
    
    void acquireResource() {
        sem_wait(&mySemaphore); // sumažinti skaitiklį, blokuoti jei 0
        // Išteklio naudojimas
    }
    
    void releaseResource() {
        sem_post(&mySemaphore); // padidinti skaitiklį
    }
    
  • Sąlygos kintamieji (Condition Variables): leidžia srautams laukti tam tikro sąlygos. Paprastai naudojami kartu su mutex'ais. Laukiantis srautas atlaisvina mutex'ą ir blokuojasi, kol kitas srautas jį informuos apie sąlygos įvykdymą.

    #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(); // pranešimas vienam laukiančiam srautui
    }
    
    int consumer() {
        std::unique_lock<std::mutex> lock(myMutex);
        myCondition.wait(lock, [&]{ return !myQueue.empty(); }); // sąlygos laukimas
        int value = myQueue.front();
        myQueue.pop();
        return value;
    }
    
  • Atominių kintamųjų (Atomic Variables): leidžia atlikti paprastus veiksmus (skaityti, rašyti, modifikuoti) atominiu būdu, nereikalaujant naudoti mutex'ų šiems konkretiems veiksmams.

    #include <atomic>
    
    std::atomic_int atomicCounter(0);
    
    void incrementCounter() {
        atomicCounter++; // atominis didinimas
    }
    
  • Barjerai (Barriers): sinchronizuoja kelis srautus taip, kad nė vienas jų negali tęsti vykdymo, kol visi nepasieks barjero.

    #include <barrier> // C++20
    
    std::barrier myBarrier(3); // barjeras trims srautams
    
    void workerThread() {
        // Darbo dalies vykdymas
        myBarrier.arrive_and_wait(); // laukia visų srautų prie barjero
        // Sekančios darbo dalies vykdymas
    }
    

Pasirinkimas priklauso nuo srautų sąveikos pobūdžio:

  • MUTEX'ai: dažniausiai naudojamas bendriems duomenims apsaugoti.
  • Semaforai: valdo prieigą prie riboto kiekio išteklių.
  • Sąlygos kintamieji: laukia tam tikro įvykio ar būsenos.
  • Atominiai kintamieji: efektyvus paprastų, atominių operacijų vykdymas.
  • Barjerai: srautų sinchronizavimas siekiant pereiti į kitą etapą.