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ų.