Sobes.tech
Middle
198

Kako sinhronizovati interakciju između niti?

Одговор од АИ

sobes.tech АИ

Постоји неколико основних механизама за синхронизацију и интеракцију између нити у 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(); // Чекање док све нитке не достигну баријеру
        // Рад после баријере
    }
    

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