Sobes.tech
Middle

Чӣ гуна метавон ҳамкории байни ҷараёнҳоро ҳамоҳанг кард?

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(); // Очікування, поки всі потоки не досягнуть бар’єра
        // Робота після бар’єра
    }
    

Вибір конкретного механізму залежить від характеру взаємодії та спільних ресурсів.