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);
    }
    
  • Четене-писане заключвания (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(); // Очакване, докато всички нишки достигнат бариерата
        // Работа след бариерата
    }
    

Изборът на конкретен механизъм зависи от характера на взаимодействието и споделените ресурси.