Sobes.tech
Middle
200

Kaip galima sinchronizuoti tarpų sąveiką?

Atsakymas iš AI

sobes.tech AI

Yra keletas pagrindinių mechanizmų, naudojamų sinchronizacijai tarp sriegių C/C++:

  • MUTEX'ai (Mutual Exclusion Locks): Užtikrina išskirtinį prieigą prie bendro ištekliaus. Srautas, kuris įgyja mutex'ą, blokuoja kitus srautus, bandančius jį įgyti, kol jis nebus atlaisvintas.

    #include <mutex>
    
    std::mutex my_mutex;
    
    void my_thread_function() {
        my_mutex.lock(); // Įgyti mutex'ą
        // Darbas su bendru ištekliu
        my_mutex.unlock(); // Atlaisvinti mutex'ą
    }
    

    Arba naudojant RAII:

    #include <mutex>
    #include <lock_guard>
    
    std::mutex my_mutex;
    
    void my_thread_function() {
        std::lock_guard<std::mutex> lock(my_mutex); // Įgyti mutex'ą kuriant objektą
        // Darbas su bendru ištekliu
        // Mutex automatiškai atlaisvinamas išeinant iš apimties
    }
    
  • Semaforai (Semaphores): Bendras mutex'ų išplėtimas. Laikosi skaitiklio, kuris leidžia tam tikram skaičiui sriegių vienu metu pasiekti išteklių.

    #include <semaphore.h> // POSIX semaforams
    #include <windows.h> // Windows semaforams
    
    sem_t my_semaphore; // POSIX semaforas
    
    void my_thread_function() {
        sem_wait(&my_semaphore); // Sumažinti semaforo skaitiklį, blokuoti jei 0
        // Darbas su ištekliu
        sem_post(&my_semaphore); // Padidinti semaforo skaitiklį
    }
    

    (Pastaba: Standartinis C++ tiesiogiai neįtraukia semaforų, tačiau jie prieinami per sisteminius bibliotekų ar trečiųjų šalių įgyvendinimus)

  • Sąlyginės kintamosios (Condition Variables): Naudojamos tam, kad srautas galėtų laukti tam tikro sąlygos įvykdymo, tuo pačiu išlaisvindamas mutex'ą. Kitas srautas gali pranešti, kad sąlyga įvykdyta.

    #include <mutex>
    #include <condition_variable>
    
    std::mutex my_mutex;
    std::condition_variable my_cv;
    bool condition_met = false;
    
    void waiting_thread() {
        std::unique_lock<std::mutex> lock(my_mutex);
        my_cv.wait(lock, []{ return condition_met; }); // Laukti sąlygos įvykdymo
        // Sąlyga įvykdyta, darbas su ištekliu
    }
    
    void notifying_thread() {
        std::unique_lock<std::mutex> lock(my_mutex);
        condition_met = true;
        lock.unlock(); // Išlaisvinti mutex'ą prieš pranešimą (pasirinktinai, bet rekomenduojama)
        my_cv.notify_one(); // Pranešti vienam laukiančiam srautui
        // arba
        // my_cv.notify_all(); // Pranešti visiems laukiančiam srautams
    }
    
  • Atomarinės operacijos (Atomic Operations): Leidžia vykdyti paprastas operacijas su kintamaisiais (pvz., padidinimas, sumažinimas) kaip vieną, nepadalijamą veiksmą, nereikalaujant aiškios užrakinimo.

    #include <atomic>
    
    std::atomic<int> counter(0);
    
    void my_thread_function() {
        counter++; // Atomarinis padidinimas
        // Arba:
        // counter.fetch_add(1);
    }
    
  • Skaitmenų skaitymo-rašo užraktai (Shared Mutexes): Leidžia keliems srautams skaityti duomenis vienu metu, bet tik vienam rašyti.

    #include <shared_mutex> // C++17 ir aukštesnės versijos
    
    std::shared_mutex my_shared_mutex;
    
    void read_thread() {
        my_shared_mutex.lock_shared(); // Užrakinti skaitymui
        // Skaityti duomenis
        my_shared_mutex.unlock_shared(); // Atlaisvinti skaitymui
    }
    
    void write_thread() {
        my_shared_mutex.lock(); // Užrakinti rašymui (ekskliuzyvus)
        // Rašyti duomenis
        my_shared_mutex.unlock(); // Atlaisvinti rašymui
    }
    
  • Barjerai (Barriers): Leidžia grupei srautų laukti, kol visi pasieks tam tikrą tašką savo vykdyme, prieš tęsiant.

    #include <barrier> // C++20
    
    std::barrier sync_point(4); // Barjeras 4 srautams
    
    void my_thread_function() {
        // Darbas prieš barjerą
        sync_point.arrive_and_wait(); // Laukti, kol visi pasieks barjerą
        // Darbas po barjero
    }
    

Pasirinkimas priklauso nuo sąveikos pobūdžio ir bendrinamų išteklių.