Jak lze synchronizovat interakci mezi vlákny?
sobes.tech AI
Odpověď od AI
Existuje několik hlavních mechanismů synchronizace a interakce mezi vlákny v C/C++:
-
Mutexy (Mutually Exclusive Locks): Zajišťují exkluzivní přístup ke sdílenému zdroji. Vlákno, které mutex uzamkne, blokuje ostatní vlákna, dokud mutex neuvolní.
#include <mutex> std::mutex my_mutex; void my_thread_function() { my_mutex.lock(); // Uzamčení mutexu // Práce se sdíleným zdrojem my_mutex.unlock(); // Odemykání mutexu }Nebo s RAII:
#include <mutex> #include <lock_guard> std::mutex my_mutex; void my_thread_function() { std::lock_guard<std::mutex> lock(my_mutex); // Uzamčení mutexu při vytvoření objektu // Práce se sdíleným zdrojem // Mutex bude automaticky odemčen při opuštění rozsahu } -
Semafory (Semaphores): Obecnější než mutexy. Udržují čítač, který umožňuje určitý počet vláken současně přistupovat ke zdroji.
#include <semaphore.h> // Pro POSIX semafory #include <windows.h> // Pro Windows semafory sem_t my_semaphore; // POSIX semafor void my_thread_function() { sem_wait(&my_semaphore); // Snížení čítače semaforu, zablokování pokud je 0 // Práce se zdrojem sem_post(&my_semaphore); // Zvýšení čítače semaforu }(Poznámka: Standard C++ přímo neobsahuje semafory, ale jsou dostupné přes systémové knihovny nebo třetí strany.)
-
Podmíněné proměnné (Condition Variables): Umožňují vláknu čekat na určitý stav, přičemž uvolní mutex. Jiná vlákna mohou oznámit, že podmínka je splněna.
#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; }); // Čekání na splnění podmínky // Podmínka splněna, práce se zdrojem } void notifying_thread() { std::unique_lock<std::mutex> lock(my_mutex); condition_met = true; lock.unlock(); // Uvolnění mutexu před oznámením (volitelné, ale doporučené) my_cv.notify_one(); // Oznámení jednomu čekajícímu vláknu // nebo // my_cv.notify_all(); // Oznámení všem čekajícím vláknům } -
Atomické operace (Atomic Operations): Umožňují provádět jednoduché operace nad proměnnými (například inkrementace, dekrementace) jako nedělitelnou akci bez nutnosti explicitního zamykání mutexu.
#include <atomic> std::atomic<int> counter(0); void my_thread_function() { counter++; // Atomická inkrementace // Nebo: // counter.fetch_add(1); } -
Sdílené zámky (Shared Mutexes): Umožňují více vláknům číst data současně, ale pouze jednomu zapisovat.
#include <shared_mutex> // C++17 a vyšší std::shared_mutex my_shared_mutex; void read_thread() { my_shared_mutex.lock_shared(); // Zamknout pro čtení // Čtení dat my_shared_mutex.unlock_shared(); // Odemknout pro čtení } void write_thread() { my_shared_mutex.lock(); // Zamknout pro zápis (exkluzivní) // Zápis dat my_shared_mutex.unlock(); // Odemknout pro zápis } -
Barriéry (Barriers): Umožňují skupině vláken čekat, dokud všechna nedosáhnou určitého bodu ve své vykonávací sekvenci, před pokračováním.
#include <barrier> // C++20 std::barrier sync_point(4); // Barikáda pro 4 vlákna void my_thread_function() { // Práce před bariérou sync_point.arrive_and_wait(); // Čekání, dokud všechna vlákna nedosáhnou bariéry // Práce po bariéře }
Volba konkrétního mechanismu závisí na povaze interakce a sdílených zdrojů.