Kuidas saab niitide vahelist suhtlust sünkroniseerida?
sobes.tech AI
Vastus AI-lt
On olemas mitu peamist mehhanismi, mis kasutavad sünkroniseerimiseks lõimede vahel C/C++:
-
Mutexid (Mutexes): Tagavad eksklusiivse juurdepääsu jagatud ressursile. Lõim, mis omandab mutexi, blokeerib teised lõimed, kes püüavad seda omandada, kuni mutex vabastatakse.
#include <mutex> std::mutex my_mutex; void my_thread_function() { my_mutex.lock(); // Mutexi omandamine // Töö jagatud ressursiga my_mutex.unlock(); // Mutexi vabastamine }Või RAII kasutades:
#include <mutex> #include <lock_guard> std::mutex my_mutex; void my_thread_function() { std::lock_guard<std::mutex> lock(my_mutex); // Mutexi omandamine objekti loomisel // Töö jagatud ressursiga // Mutex vabastatakse automaatselt väljapääsuga ulatusest } -
Semaforid (Semaphores): Mütakse laienemine. Hoiab arvestit, mis võimaldab teatud arvul lõimedel samaaegselt juurdepääsu ressursile.
#include <semaphore.h> // POSIX semaforid #include <windows.h> // Windows semaforid sem_t my_semaphore; // POSIX semafor void my_thread_function() { sem_wait(&my_semaphore); // Vähendab semafori arvestit, blokeerib kui 0 // Töö ressursiga sem_post(&my_semaphore); // Suurendab semafori arvestit }(Märkus: Standard C++ ei sisalda semaforeid otse, kuid need on saadaval süsteemiraamatukogude või kolmanda osapoole teostuste kaudu)
-
Tingimusmuutujad (Condition Variables): Kasutatakse selleks, et lõim saaks oodata teatud tingimuse täitumist, vabastades samal ajal mutexi. Teine lõim võib teavitada ootavat, et tingimus on täidetud.
#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; }); // Oodata tingimuse täitumist // Tingimus täidetud, töö ressursiga } void notifying_thread() { std::unique_lock<std::mutex> lock(my_mutex); condition_met = true; lock.unlock(); // Vabastada mutex enne teavitamist (valikuline, kuid soovitatav) my_cv.notify_one(); // Teavitada ühte ootavat lõime // või // my_cv.notify_all(); // Teavitada kõiki ootavaid lõime } -
Atomaarsed operatsioonid (Atomic Operations): Annab võimaluse teha lihtsaid operatsioone muutujate üle (näiteks, suurendamine, vähendamine) ühe tervikliku, jagamatuna toiminguna, ilma mutexi otsese lukustamiseta.
#include <atomic> std::atomic<int> counter(0); void my_thread_function() { counter++; // Atomaarselt suurendamine // Või: // counter.fetch_add(1); } -
Lugemis- ja kirjutuslukk (Shared Mutex): Annab mitmele lõimile võimaluse samaaegselt lugeda andmeid, kuid ainult ühele kirjutada.
#include <shared_mutex> // C++17 ja uuemad std::shared_mutex my_shared_mutex; void read_thread() { my_shared_mutex.lock_shared(); // Lukustada lugemiseks // Andmete lugemine my_shared_mutex.unlock_shared(); // Vabastada lugemiseks } void write_thread() { my_shared_mutex.lock(); // Lukustada kirjutamiseks (eksklusiivne) // Andmete kirjutamine my_shared_mutex.unlock(); // Vabastada kirjutamiseks } -
Barjäärid (Barriers): Annab grupile lõimidele võimaluse oodata, kuni kõik jõuavad teatud punkti oma täitmises, enne kui jätkata.
#include <barrier> // C++20 std::barrier sync_point(4); // Barjäär 4 lõimale void my_thread_function() { // Enne barjääri tehtav töö sync_point.arrive_and_wait(); // Oodata, kuni kõik jõuavad barjääri // Pärast barjääri tehtav töö }
Valik konkreetse mehhanismi vahel sõltub suhtluse iseloomust ja jagatud ressurssidest.