Sobes.tech
Middle

Kuidas saab sünkroniseerida niitide vahelist suhtlust?

sobes.tech AI

Vastus AI-lt

C++-s ir vairāki galvenie mehānismi pavedienu sinhronizācijai:

  • Mutexes (Mutexes): nodrošina izņēmumu. Tik viens pavediens var piederēt mutexam vienlaikus. Izmanto kopēju resursu aizsardzībai pret vienlaicīgu piekļuvi.

    #include <mutex>
    
    std::mutex myMutex;
    
    void criticalSection() {
        std::lock_guard<std::mutex> lock(myMutex); // mutex ieguve
        // Darbs ar kopēju resursu
    } // mutex automātiski atbrīvojas, izejot no apgabala
    
  • Semafori (Semaphores): pārvalda piekļuvi ierobežotam resursu skaitam. Semafors ir skaitītājs, kas norāda pieejamo resursu skaitu. Pavedieni samazina skaitītāju (resursa iegūšanai) un palielina (resursa atbrīvošanai).

    #include <semaphore.h> // bieži lieto POSIX sistēmās
    
    sem_t mySemaphore;
    
    void initSemaphore(int count) {
        sem_init(&mySemaphore, 0, count); // semafora inicializācija ar skaitītāju count
    }
    
    void acquireResource() {
        sem_wait(&mySemaphore); // skaitītāja samazināšana, bloku, ja 0
        // Resursa izmantošana
    }
    
    void releaseResource() {
        sem_post(&mySemaphore); // skaitītāja palielināšana
    }
    
  • Nosacījumu mainīgie (Condition Variables): ļauj pavedieniem gaidīt noteiktu nosacījumu. Parasti lieto kopā ar mutexiem. Gaidīšanas pavediens atbrīvo mutexu un bloķējas, kamēr cits pavediens to nebrīdina par nosacījuma izpildi.

    #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(); // paziņojums vienam gaidīgam pavedienam
    }
    
    int consumer() {
        std::unique_lock<std::mutex> lock(myMutex);
        myCondition.wait(lock, [&]{ return !myQueue.empty(); }); // nosacījuma gaidīšana
        int value = myQueue.front();
        myQueue.pop();
        return value;
    }
    
  • Atomālie mainīgie (Atomic Variables): ļauj veikt vienkāršas operācijas (lasīšana, rakstīšana, modifikācija) atomiski, bez nepieciešamības lietot mutexus šīm konkrētajām operācijām.

    #include <atomic>
    
    std::atomic_int atomicCounter(0);
    
    void incrementCounter() {
        atomicCounter++; // atomiska palielināšana
    }
    
  • Barjeras (Barriers): sinhronizē vairākus pavedienus tā, lai neviens no tiem nevar turpināt izpildi, kamēr visi ne sasniedz barjeru.

    #include <barrier> // C++20
    
    std::barrier myBarrier(3); // barjera trim pavedieniem
    
    void workerThread() {
        // Darba daļas izpilde
        myBarrier.arrive_and_wait(); // gaidīt visus pavedienus pie barjeras
        // Nākamās darba daļas izpilde
    }
    

Izvēle ir atkarīga no saskarsmes rakstura starp pavedieniem:

  • Mutexi: visbiežāk izmantots kopēju datu aizsardzībai.
  • Semafori: pārvalda piekļuvi ierobežotam resursu skaitam.
  • Nosacījumu mainīgie: gaida noteiktu notikumu vai stāvokli.
  • Atomālie mainīgie: efektīva vienkāršu, atomisku operāciju izpilde.
  • Barjeras: pavedienu sinhronizācija, lai pārietu uz nākamo posmu.