C++ Academy · Oppitunti

Ehtomuuttujat ja työntekijämallit

Koordinoi säikeitä std::condition_variablella ja perinteisellä työskentelysäiemallilla.

Oppitunti 3/414 vaihetta

Ehtomuuttujat ja työntekijämallit on ilmainen C++ Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu C++ Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. C++ Academy-kurssilla on yhteensä 4 oppituntia.

Mikä on ehtomuuttuja?

Ehtomuuttujan avulla säie voi odottaa, kunnes toinen säie ilmoittaa ehdon muuttuneen. Ehtomuuttujia käytetään tuottajien ja kuluttajien koordinointiin.

std::condition_variable-perusteet

Ehtomuuttuja toimii yhdessä std::mutex-olion ja predikaatin kanssa. Odottava säie vapauttaa lukon odottamisen ajaksi ja hankkii sen uudelleen herätessään.

#include <condition_variable>
#include <mutex>
#include <queue>

std::mutex mtx;
std::condition_variable cv;
std::queue<int> tasks;
bool done = false;

Ehdon odottaminen

Käyttäkää cv.wait(lock, predicate)-kutsua. Se avaa mutexin lukituksen atomisesti ja nukkuu, kunnes säie herätetään. Herättyään se lukitsee mutexin uudelleen ja tarkistaa predikaatin; jos ehto ei täyty, se jatkaa nukkumista.

std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return !tasks.empty() || done; });

Ilmoittaminen

Tuottajasäie kutsuu cv.notify_one()- tai cv.notify_all()-funktiota tilan muuttamisen jälkeen. Lukon tulee olla pidettynä tilan muuttamisen ajan.

{
    std::lock_guard<std::mutex> lock(mtx);
    tasks.push(42);
}
cv.notify_one();

Tuottaja–kuluttaja-malli

Klassinen esimerkki: tuottajat lisäävät tehtäviä jonoon ja kuluttajat odottavat tehtäviä.

void consumer() {
    while (true) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, [] { return !tasks.empty() || done; });
        if (done && tasks.empty()) break;
        int task = tasks.front();
        tasks.pop();
        lock.unlock();
        process(task);
    }
}

Virheelliset heräämiset

Ehtomuuttujaa odottava säie voi herätä ilman ilmoitusta. Siksi wait ottaa predikaatin — se tarkistaa ehdon uudelleen jokaisen heräämisen yhteydessä.

notify_one vs notify_all

Käyttäkää notify_one-funktiota, kun yksi odottaja voi jatkaa etenemistä. Käyttäkää notify_all-funktiota, kun tilan muutos vaikuttaa kaikkiin odottajiin (esimerkiksi sammutussignaali).

Ajastetut odotukset

wait_for(lock, duration) ja wait_until(lock, time_point) herättävät joko ilmoituksen saapuessa tai aikakatkaisun jälkeen.

if (cv.wait_for(lock, 1s, [] { return ready; })) {
    /* condition met */
} else {
    /* timed out */
}

Työtekijäpoolin runko

Yleinen malli: kiinteä joukko työtekijäsäikeitä noutaa tehtäviä jaetusta jonosta. Rakentamiseen tarvitaan mutex, condition_variable, queue ja atominen pysäytyslippu.

Kadonneiden heräämisten välttäminen

Muuttakaa jaettua tilaa ja kutsukaa notify_*-funktiota aina mutexin ollessa pidettynä tilan muutoksen ajan (lukon vapauttaminen juuri ennen ilmoitusta on sallittua, kunhan järjestys varmistetaan). Muuten odottaja voi jäädä ilman ilmoitusta.

std::counting_semaphore (C++20)

Yksinkertaiseen laskentaan perustuvaan signalointiin C++20 lisäsi std::counting_semaphore-luokan — se on joissakin malleissa ehtomuuttujia yksinkertaisempi.

Varokaa lukkiutumista

Useiden lukkojen pitäminen ehtomuuttujaa odotettaessa voi johtaa lukkiutumiseen. Hankkikaa lukot aina yhdenmukaisessa järjestyksessä ja käyttäkää useille mutex-olioille std::scoped_lock-luokkaa.

Pikatarkistus

Miksi cv.wait(lock, predicate) ottaa predikaatin, vaikka haluatte vain odottaa ilmoitusta?

Kertaus

Ehtomuuttuja koordinoi tilan muutosta odottavia säikeitä. Käyttäkää wait(lock, predicate)-kutsua virheellisten heräämisten käsittelyyn, muuttakaa tilaa mutexin suojassa ja kutsukaa sen jälkeen notify_one- tai notify_all-funktiota.

Aloita maksutta

Opi C++ tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
51
Oppitunnit
203

Usein kysytyt kysymykset

Onko oppitunti ”Ehtomuuttujat ja työntekijämallit” ilmainen?

Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa C++ Academy-oppimispolun 3 oppituntia, myös oppitunnin “Ehtomuuttujat ja työntekijämallit”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. C++ Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Ehtomuuttujat ja työntekijämallit”?

Koordinoi säikeitä std::condition_variablella ja perinteisellä työskentelysäiemallilla. Harjoittelet C++ Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni C++ Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin C++ Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.

Kuinka kauan ”Ehtomuuttujat ja työntekijämallit”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä C++ Academy-oppitunnilla?

Kyllä. Jokainen C++ Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. std::thread: liittyminen ja irrottaminen
  2. std::mutex, lock_guard ja unique_lock
  3. Ehtomuuttujat ja työntekijämallit
  4. std::async- ja std::future-perusteet
← Takaisin: C++ Academy