Ako synchronizovať interakciu medzi vláknami?
sobes.tech AI
Odpoveď od AI
Existuje niekoľko hlavných mechanizmov synchronizácie interakcie medzi vláknami v C/C++:
-
Mutexy (Mutually Exclusive Locks): Zabezpečujú exkluzívny prístup ku zdieľanému zdroju. Vlákno, ktoré získalo mutex, blokuje ostatné vlákna, ktoré sa ho snažia získať, až kým mutex neuvoľní.
#include <mutex> std::mutex my_mutex; void my_thread_function() { my_mutex.lock(); // Získanie mutexu // Práca so zdieľaným zdrojom my_mutex.unlock(); // Uvoľnenie mutexu }Alebo s použitím RAII:
#include <mutex> #include <lock_guard> std::mutex my_mutex; void my_thread_function() { std::lock_guard<std::mutex> lock(my_mutex); // Získanie mutexu pri vytvorení objektu // Práca so zdieľaným zdrojom // Mutex sa automaticky uvoľní pri opustení rozsahu } -
Semafory (Semaphores): Generalizácia mutexov. Podporujú počítadlo, ktoré umožňuje určitý počet vlákien súčasne pristupovať ku zdroju.
#include <semaphore.h> // Pre POSIX semafory #include <windows.h> // Pre Windows semafory sem_t my_semaphore; // POSIX semafor void my_thread_function() { sem_wait(&my_semaphore); // Znížiť počítadlo semaforu, zablokovať ak je 0 // Práca so zdrojom sem_post(&my_semaphore); // Zvýšiť počítadlo semaforu }(Poznámka: Štandard C++ priamo neobsahuje semafory, ale sú dostupné cez systémové knižnice alebo tretie strany.)
-
Podmienkové premenné (Condition Variables): Používajú sa na to, aby vlákno mohlo čakať na určitú podmienku, pričom uvoľní mutex. Iné vlákno môže oznámiť, že podmienka bola splnená.
#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; }); // Čakať na splnenie podmienky // Podmienka je splnená, práca so zdrojom } void notifying_thread() { std::unique_lock<std::mutex> lock(my_mutex); condition_met = true; lock.unlock(); // Uvoľniť mutex pred oznámením (voliteľné, ale odporúčané) my_cv.notify_one(); // Oznámiť jedno čakajúce vlákno // alebo // my_cv.notify_all(); // Oznámiť všetky čakajúce vlákna } -
Atómové operácie (Atomic Operations): Umožňujú vykonávať jednoduché operácie nad premennými (napríklad inkrement, dekrement) ako jednotný, nedeliteľný krok, bez potreby explicitného zámku mutex.
#include <atomic> std::atomic<int> counter(0); void my_thread_function() { counter++; // Atómový inkrement // Alebo: // counter.fetch_add(1); } -
Read-Write Locks (Shared Mutexes): Umožňujú viacerým vláknam čítať dáta súčasne, ale len jednému vlákno zapisovať dáta.
#include <shared_mutex> // C++17 a vyššie std::shared_mutex my_shared_mutex; void read_thread() { my_shared_mutex.lock_shared(); // Získanie pre čítanie // Čítanie dát my_shared_mutex.unlock_shared(); // Uvoľnenie pre čítanie } void write_thread() { my_shared_mutex.lock(); // Získanie pre zápis (exkluzívne) // Zápis dát my_shared_mutex.unlock(); // Uvoľnenie pre zápis } -
Baréry (Barriers): Umožňujú skupine vlákien čakať, kým všetky nedosiahnu určitý bod vo svojom vykonávaní, predtým než pokračujú.
#include <barrier> // C++20 std::barrier sync_point(4); // Bariera pre 4 vlákna void my_thread_function() { // Práca pred bariérou sync_point.arrive_and_wait(); // Čakanie, kým všetky vlákna nedosiahnu bariéru // Práca po bariére }
Výber konkrétneho mechanizmu závisí od charakteru interakcie a zdieľaných zdrojov.