Чӣ гуна метавон ҳамкории байни ҷараёнҳоро ҳамоҳанг кард?
sobes.tech AI
Ҷавоб аз AI
Існує кілька основних механізмів синхронізації взаємодії між потоками в C/C++:
-
Мютекси (Mutexes): Забезпечують ексклюзивний доступ до спільного ресурсу. Потік, який захопив мютекс, блокує інші потоки, які намагаються його захопити, доки не звільнить мютекс.
#include <mutex> std::mutex my_mutex; void my_thread_function() { my_mutex.lock(); // Захоплення мютексу // Робота з спільним ресурсом my_mutex.unlock(); // Вивільнення мютексу }Або з використанням RAII:
#include <mutex> #include <lock_guard> std::mutex my_mutex; void my_thread_function() { std::lock_guard<std::mutex> lock(my_mutex); // Захоплення мютексу при створенні об’єкта // Робота з спільним ресурсом // Мютекс автоматично звільниться при виході з області } -
Семафори (Semaphores): Узагальнення мютексів. Підтримують лічильник, який дозволяє заданій кількості потоків одночасно отримати доступ до ресурсу.
#include <semaphore.h> // Для POSIX-семафорів #include <windows.h> // Для Windows-семафорів sem_t my_semaphore; // POSIX-семафор void my_thread_function() { sem_wait(&my_semaphore); // Зменшити лічильник семафора, заблокувати, якщо 0 // Робота з ресурсом sem_post(&my_semaphore); // Збільшити лічильник семафора }(Примітка: Стандарт C++ не включає семафори безпосередньо, але вони доступні через системні бібліотеки або сторонні реалізації.)
-
Умовні змінні (Condition Variables): Використовуються для того, щоб потік міг очікувати на настання певної умови, при цьому звільняючи мютекс. Інший потік може повідомити очікуючий про виконання умови.
#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; }); // Чекати виконання умови // Умова виконана, робота з ресурсом } void notifying_thread() { std::unique_lock<std::mutex> lock(my_mutex); condition_met = true; lock.unlock(); // Вивільнити мютекс перед повідомленням (опціонально, але рекомендується) my_cv.notify_one(); // Повідомити один очікуючий потік // або // my_cv.notify_all(); // Повідомити всі очікуючі потоки } -
Атомарні операції (Atomic Operations): Дозволяють виконувати прості операції над змінними (наприклад, інкремент, декремент) як єдину, неділиму дію, без явного блокування мютексу.
#include <atomic> std::atomic<int> counter(0); void my_thread_function() { counter++; // Атомарний інкремент // Або: // counter.fetch_add(1); } -
Read-Write Locks (Shared Mutexes): Дозволяють кільком потокам читати дані одночасно, але тільки одному потоку записувати дані.
#include <shared_mutex> // C++17 і вище std::shared_mutex my_shared_mutex; void read_thread() { my_shared_mutex.lock_shared(); // Захоплення для читання // Читання даних my_shared_mutex.unlock_shared(); // Вивільнення для читання } void write_thread() { my_shared_mutex.lock(); // Захоплення для запису (ексклюзивне) // Запис даних my_shared_mutex.unlock(); // Вивільнення для запису } -
Бар’єри (Barriers): Дозволяють групі потоків чекати, поки всі не досягнуть певної точки у своєму виконанні, перед тим як продовжити.
#include <barrier> // C++20 std::barrier sync_point(4); // Бар’єр для 4 потоків void my_thread_function() { // Робота перед бар’єром sync_point.arrive_and_wait(); // Очікування, поки всі потоки не досягнуть бар’єра // Робота після бар’єра }
Вибір конкретного механізму залежить від характеру взаємодії та спільних ресурсів.