Cum se poate sincroniza interacțiunea între fire?
sobes.tech AI
Răspuns de la AI
Există mai multe mecanisme principale de sincronizare a firelor în C++:
-
Mutex-uri: Asigură excluderea mutuală. Doar un fir poate deține un mutex într-un moment dat. Sunt folosite pentru a proteja resursele comune împotriva accesului simultan.
#include <mutex> std::mutex myMutex; void criticalSection() { std::lock_guard<std::mutex> lock(myMutex); // Achiziționarea mutex-ului // Lucru cu resursa comună } // Mutex-ul este eliberat automat la ieșirea din scop -
Semaforuri: Controlează accesul la resurse limitate. Un semafor are un contor care indică numărul de resurse disponibile. Firurile pot diminua (pentru a obține o resursă) sau crește (pentru a elibera).
#include <semaphore.h> // Folosit de obicei în sistemele POSIX sem_t mySemaphore; void initSemaphore(int count) { sem_init(&mySemaphore, 0, count); // Inițializare semafor cu contorul count } void acquireResource() { sem_wait(&mySemaphore); // Diminuați contorul, blocați dacă este 0 // Utilizarea resursei } void releaseResource() { sem_post(&mySemaphore); // Creșteți contorul } -
Variabile de condiție: Permite firelor să aștepte anumite condiții. De obicei sunt folosite împreună cu mutexuri. Un fir care așteaptă eliberează mutex-ul și se blochează până când alt fir îl notifică că condiția a fost îndeplinită.
#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(); // Notificare unui fir în așteptare } int consumer() { std::unique_lock<std::mutex> lock(myMutex); myCondition.wait(lock, [&]{ return !myQueue.empty(); }); // Așteptare condiție int value = myQueue.front(); myQueue.pop(); return value; } -
Variabile atomice: Permite efectuarea operațiilor simple (citire, scriere, modificare) în mod atomic, fără a fi nevoie de mutexuri pentru aceste operații.
#include <atomic> std::atomic_int atomicCounter(0); void incrementCounter() { atomicCounter++; // Creștere atomică } -
Barriere: Sincronizează mai multe fire astfel încât nici unul să nu poată continua până când toți nu au atins bariera.
#include <barrier> // C++20 std::barrier myBarrier(3); // Barieră pentru 3 fire void workerThread() { // Executarea unei părți a muncii myBarrier.arrive_and_wait(); // Așteptarea tuturor firelor la barieră // Executarea următoarei părți a muncii }
Alegerea unui mecanism specific depinde de natura interacțiunii dintre fire:
- Mutex-uri: Cel mai comun mod de a proteja datele comune.
- Semaforuri: Gestionarea accesului la resurse limitate.
- Variabile de condiție: Așteptarea apariției unui eveniment sau stare specifică.
- Variabile atomice: Executarea eficientă a operațiilor simple și atomice.
- Barriere: Sincronizarea firelor pentru trecerea comună la etapa următoare.