Kako sinhronizovati interakciju između niti?
sobes.tech АИ
Одговор од АИ
Postoji nekoliko osnovnih mehanizama za sinhronizaciju niti u C++:
-
Muteksi (Mutexi): Osiguravaju međusobno isključivanje. Samo jedna nit može imati muteks u bilo kom trenutku. Koriste se za zaštitu zajedničkih resursa od istovremenog pristupa.
#include <mutex> std::mutex myMutex; void criticalSection() { std::lock_guard<std::mutex> lock(myMutex); // Zauzimanje muteksa // Rad sa zajedničkim resursom } // Muteks se automatski oslobađa pri izlasku iz opsega -
Semafori: Upravljaju pristupom ograničenom broju resursa. Semafor ima brojač koji ukazuje na broj dostupnih resursa. Niti smanjuju (za dobijanje resursa) i povećavaju (za oslobađanje resursa) taj brojač.
#include <semaphore.h> // Obično se koristi u POSIX sistemima sem_t mySemaphore; void initSemaphore(int count) { sem_init(&mySemaphore, 0, count); // Inicijalizacija semafora sa brojačem count } void acquireResource() { sem_wait(&mySemaphore); // Smanjenje brojača, blokira ako je 0 // Korišćenje resursa } void releaseResource() { sem_post(&mySemaphore); // Povećanje brojača } -
Uslovne promenljive: Omogućavaju nitima da čekaju određeni uslov. Obično se koriste zajedno sa muteksima. Nit koja čeka uslov oslobađa muteks i blokira se dok je ne obavesti druga nit da je uslov ispunjen.
#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(); // Obaveštavanje jedne čekajuće niti } int consumer() { std::unique_lock<std::mutex> lock(myMutex); myCondition.wait(lock, [&]{ return !myQueue.empty(); }); // Čekanje uslova int value = myQueue.front(); myQueue.pop(); return value; } -
Atomarne promenljive: Omogućavaju izvršavanje jednostavnih operacija (čitanje, pisanje, modifikacija) atomskim putem, bez potrebe za korišćenjem muteksa za te operacije.
#include <atomic> std::atomic_int atomicCounter(0); void incrementCounter() { atomicCounter++; // Atomicko povećanje } -
Barijere: Sinhronizuju više niti tako da nijedna ne može nastaviti izvršavanje dok sve ne dostignu barijeru.
#include <barrier> // C++20 std::barrier myBarrier(3); // Barijera za 3 niti void workerThread() { // Izvršavanje dela posla myBarrier.arrive_and_wait(); // Čekanje svih niti na barijeri // Izvršavanje sledećeg dela posla }
Izbor određenog mehanizma zavisi od karaktera interakcije između niti:
- Muteksi: Najčešći način zaštite zajedničkih podataka.
- Semafori: Upravljanje pristupom ograničenom broju resursa.
- Uslovne promenljive: Čekanje niti na određeni događaj ili stanje.
- Atomarne promenljive: Efikasno izvršavanje jednostavnih, atomskih operacija.
- Barijere: Sinhronizacija niti za zajednički prelaz na sledeći korak.