Hlavní navigace

Programování pod Linuxem pro všechny (20)

Jakub Matys 18. 6. 2004

V minulém dílu jsme si vysvětlovali synchronizaci vláken pomocí podmíněné proměnné. Dnes bych vám chtěl ukázat praktické uplatnění této metody.

Abychom problém vyřešili, potřebujeme nějakým způsobem zamknout příznak a podmíněnou proměnnou spolu s mutexem. Linux nám takový mechanismus poskytuje. Každá podmíněná proměnná musí být v konjunkci s mutexem; pokud dodržíme tento postup, bude funkce vlákna logicky poskládána z následujících kro­ků:

  1. Cyklus ve funkci thread_function uzamkne mutex a přečte hodnotu příznaku.
  2. Je-li příznak nastaven, odemkne mutex a provede svůj kód.
  3. Když příznak není nastaven, automaticky se odemkne mutex a vlákno bude čekat na podmíněnou proměnnou.

V uvedeném postupu představuje kritickou vlastnost bod 3, ve kterém operační systém umožňuje odemknout mutex a čekat na podmíněnou proměnnou automaticky, aniž by mělo jiné vlákno možnost intervenovat. Takto je vyloučeno, že by jiné vlákno mohlo změnit hodnotu příznaku a signalizovat změnu podmíněné proměnné mezi tím, kdy funkce thread_function testuje hodnotu příznaku a pak čeká na změnu podmíněné proměnné.

Podmíněná proměnná je reprezentována instancí proměnné typu pthread_cond_t. Každá podmíněná proměnná musí být doprovázena mutexem. V následujícím seznamu naleznete funkce umožňující manipulaci s podmíněnou proměnnou.

  • Funkce pthread_cond_init() inicializuje podmíněnou proměnnou. Prvním argumentem je ukazatel na instanci proměnné pthread_cond_t. Druhým argumentem je ukazatel na objekt definující atributy podmíněné proměnné a je systémem ignorován. Mutex musí být inicializován odděleně.
  • Funkce pthread_cond_sig­nal() signalizuje změnu podmíněné proměnné. Pouze jedno vlákno, které je blokováno podmíněnou proměnnou, bude odblokováno. Pokud není žádné jiné vlákno zablokováno podmíněnou proměnnou, je signál ignorován. Argumentem je ukazatel na instanci proměnné pthread_cond_t. Podobná funkce, pthread_cond_bro­adcast(), odblokuje všechna vlákna, která jsou zablokována podmíněnou proměnnou.
  • Funkce pthread_cond_wait() zablokuje volající vlákno, dokud není signalizována změna podmíněné proměnné. Argumentem je ukazatel na instanci proměnné pthread_cond_t. Druhým argumentem je ukazatel na instanci mutexu pthread_mutex_t. Když je funkce volána, musí už být mutex zablokován volajícím vláknem. Tato funkce automaticky odemkne mutex a zablokuje se podmíněnou proměnnou. Když je signalizována změna podmíněné proměnné a volající vlákno se odblokuje, funkcepthread_con­d_wait() automaticky znovu získá uzamčení mutexu.

Kdykoliv váš program provede akci, jež může změnit smysl podmínky, kterou chráníte prostřednictvím podmíněné proměnné, měl by realizovat následujcí kroky.

  1. Uzamkněte mutex doprovázející podmíněnou proměnnou.
  2. Proveďte kteroukoliv akci, jež by mohla změnit smysl podmínky.
  3. Signalizujte nebo vyšlete podmíněnou proměnnou.
  4. Odemkněte mutex doprovázející podmíněnou proměnnou.

Následující kód obsahuje předcházející verzi našeho příkladu, přičemž nyní se zde používá podmíněná proměnná k ochraně příznaku. Ve funkci thread_function je držen zámek mutexu před kontrolou proměnné thread_flag. Tento zámek se automaticky uvolní voláním funkce pthread_cond_wait() před zablokováním a je poté automaticky získán zpět. Funkce set_thread_flag uzamyká mutex předtím, než se nastaví proměnné thread_flag a než se signalizuje mutex.

#include <pthread.h>

int thread_flag;
pthread_cond_t thread_flag_cv;
pthread_mutex_t thread_flag_mutex;

void inialize_flag()
{
  /* Inicializace mutexu a podminene promenne. */
  pthread_mutex_init(&thread_flag_mutex, NULL);
  pthread_cond_init(&thread_flag_cv, NULL);
  thread_flag = 0;
}

/* Vola funkci do_work pokud je promenna thread_flag nastavena, jinak je blokovana */

void *thread_function(void *thread_arg)
{
  while(1) {
    /* Uzamkne mutex pred zpristupnenim promenne */
    pthread_mutex_lock(&thread_flag_mutex);
    while(!thread_flag)
      /* Podminena promenna neni nastavena. Cekani na signal o zmene hodnoty promenne. Pokud obdrzi signal a uvolni vlakno, probehne smycka a bude zkontrolovana podminena promenna. */
      pthread_cond_wait(&thread_flag_cv, &thread_flag_mutex);
    /* Pokud program postoupil az sem, promenna musi byt nastavena. Odemkne mutex. */
    pthread_mutex_unlock(&thread_flag_mutex);
    /* Zavola funkci do_work */
    do_work();
  }
  return(NULL);
}

/* Nastavi hodnotu podminene promenne FLAG_VALUE */
void set_thread_flag(int flag_value)
{
  /* Uzamkne mutex pred pristupem do podminene promenne */
  pthread_mutex_lock(&thread_flag_mutex);
  /* Nastavi hodnotu podminene promenne a vysle signal o zmene promenne. Jedno vlakno bude odblokovano. */
  thread_flag = flag_value;
  pthread_cond_signal(&thread_flag_cv);
  /* Odemkne mutex */
  pthread_mutex_unlock(&thread_flag_mutex);
} 

Podmínka chráněná podmíněnou proměnnou může být libovolně složitá. Avšak před provedením jakékoliv operace, která může změnit smysl podmínky, by mělo být požadováno uzamčení mutexu a pak by se měla signalizovat podmíněná proměnná.

Tímto bych ukončil kapitolku věnovanou vláknům. Příště se podíváme na sdílenou pamět, která slouží ke komunikaci mezi procesy.

Našli jste v článku chybu?

22. 6. 2004 11:17

uživatel si přál zůstat v anonymitě

No ja si toho vsimnul uz driv. Autor tuto knihu pouziva uz od zacatku. Urcite opisuje priklady i s komentarem.

Ta kniha je volne ke stazeni http://www.advancedlinuxprogramming.com/ jak na techto strankach pisou je sirena podle Open Publication License http://www.opencontent.org/openpub/

Schvalne sem ji prosel vsechny clanky a autor se nikde o tom odkud cerpa nezminuje, ackoliv by podle licence mel.





20. 6. 2004 19:55

Jerry III (neregistrovaný)

Nemluve o tom ze pokud je to opravdu doslova obslehnuty tak je to poruseni copyrightu a proti copyrightum open source komunita nebojuje co vim.

Podnikatel.cz: K EET. Štamgast už peníze na stole nenechá

K EET. Štamgast už peníze na stole nenechá

Lupa.cz: Propustili je z Avastu, už po nich sahá ESET

Propustili je z Avastu, už po nich sahá ESET

120na80.cz: Pánové, pečujte o svoje přirození a prostatu

Pánové, pečujte o svoje přirození a prostatu

DigiZone.cz: ČRo rozšiřuje DAB do Berouna

ČRo rozšiřuje DAB do Berouna

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Root.cz: Vypadl Google a rozbilo se toho hodně

Vypadl Google a rozbilo se toho hodně

DigiZone.cz: Sony KD-55XD8005 s Android 6.0

Sony KD-55XD8005 s Android 6.0

Podnikatel.cz: 1. den EET? Problémy s pokladnami

1. den EET? Problémy s pokladnami

Vitalia.cz: Jsou čajové sáčky toxické?

Jsou čajové sáčky toxické?

120na80.cz: Rakovina oka. Jak ji poznáte?

Rakovina oka. Jak ji poznáte?

Vitalia.cz: „Připluly“ z Německa a možná obsahují jed

„Připluly“ z Německa a možná obsahují jed

Vitalia.cz: 9 největších mýtů o mase

9 největších mýtů o mase

Lupa.cz: Teletext je „internetem hipsterů“

Teletext je „internetem hipsterů“

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

Vitalia.cz: Chtějí si léčit kvasinky. Lék je jen v Německu

Chtějí si léčit kvasinky. Lék je jen v Německu

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

Lupa.cz: Co se dá měřit přes Internet věcí

Co se dá měřit přes Internet věcí

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

Vitalia.cz: Baletky propagují zdravotní superpostel

Baletky propagují zdravotní superpostel

Vitalia.cz: Tesco: Chudá rodina si koupí levné polské kuře

Tesco: Chudá rodina si koupí levné polské kuře