Hoe kan de interactie tussen threads gesynchroniseerd worden?
sobes.tech AI
Antwoord van AI
Er zijn verschillende belangrijke mechanismen voor synchronisatie en interactie tussen threads in C/C++:
-
Mutexen (Mutual Exclusions): Zorgt voor exclusieve toegang tot een gedeelde bron. Een thread die een mutex heeft vergrendeld, blokkeert andere threads die proberen dezelfde mutex te vergrendelen totdat deze wordt vrijgegeven.
#include <mutex> std::mutex my_mutex; void my_thread_function() { my_mutex.lock(); // Mutex vergrendelen // Werken met gedeelde bron my_mutex.unlock(); // Mutex ontgrendelen }Of met RAII:
#include <mutex> #include <lock_guard> std::mutex my_mutex; void my_thread_function() { std::lock_guard<std::mutex> lock(my_mutex); // Mutex vergrendelen bij creatie // Werken met gedeelde bron // Mutex wordt automatisch vrijgegeven bij het verlaten van de scope } -
Semaforen (Semaphores): Generalisatie van mutexen. Ondersteunt een teller die bepaalt hoeveel threads gelijktijdig toegang kunnen krijgen tot een bron.
#include <semaphore.h> // Voor POSIX-semaforen #include <windows.h> // Voor Windows-semaforen sem_t my_semaphore; // POSIX-semafor void my_thread_function() { sem_wait(&my_semaphore); // Teller verlagen, blokkeren als 0 // Werken met bron sem_post(&my_semaphore); // Teller verhogen }(Opmerking: C++ standaard bevat geen semaforen direct, maar ze zijn beschikbaar via systeembibliotheken of third-party implementaties.)
-
Voorwaardelijke variabelen (Condition Variables): Worden gebruikt zodat een thread kan wachten op een bepaalde voorwaarde, terwijl het mutex vrijlaat. Een andere thread kan de wachtende informeren dat de voorwaarde is vervuld.
#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; }); // Wacht op vervulling van voorwaarde // Voorwaarde vervuld, werken met bron } void notifying_thread() { std::unique_lock<std::mutex> lock(my_mutex); condition_met = true; lock.unlock(); // Vrijlaten van mutex voor notificatie (optioneel, maar aanbevolen) my_cv.notify_one(); // Informeer één wachtende thread // of // my_cv.notify_all(); // Informeer alle wachtende threads } -
Atomare operaties (Atomic Operations): Stellen eenvoudige operaties over variabelen in staat (bijvoorbeeld increment, decrement) als één ondeelbare actie, zonder expliciete lock.
#include <atomic> std::atomic<int> counter(0); void my_thread_function() { counter++; // Atomair increment // Of: // counter.fetch_add(1); } -
Read-Write Locks (Shared Mutexes): Stellen meerdere threads in staat om gelijktijdig te lezen, maar slechts één om te schrijven.
#include <shared_mutex> // C++17 en hoger std::shared_mutex my_shared_mutex; void read_thread() { my_shared_mutex.lock_shared(); // Vergrendelen voor lezen // Lezen van data my_shared_mutex.unlock_shared(); // Ontgrendelen voor lezen } void write_thread() { my_shared_mutex.lock(); // Vergrendelen voor schrijven (exclusief) // Schrijven van data my_shared_mutex.unlock(); // Ontgrendelen voor schrijven } -
Barrières (Barriers): Stellen een groep threads in staat te wachten totdat allen een bepaald punt in hun uitvoering bereiken, voordat ze verder gaan.
#include <barrier> // C++20 std::barrier sync_point(4); // Barrière voor 4 threads void my_thread_function() { // Werk vóór de barrière sync_point.arrive_and_wait(); // Wachten totdat alle threads de barrière bereiken // Werk na de barrière }
De keuze van een specifiek mechanisme hangt af van de aard van de interactie en de gedeelde bronnen.