210 likes | 354 Views
Multitasking. Schopnost operaÄnÃho systému mÃt spuÅ¡tÄ›no vÃce programů souÄasnÄ› OperaÄnà systém použÃvá hardwarové hodiny a každému běžÃcÃmu procesu pÅ™idÄ›luje tzv. Äasová kvanta
E N D
Multitasking • Schopnost operačního systému mít spuštěno více programů současně • Operační systém používá hardwarové hodiny a každému běžícímu procesu přiděluje tzv. časová kvanta • Pokud jsou časová kvanta dostatečně malá (a počítač není přetížen velkým množstvím spuštěných programů), má uživatel pocit, že všechny programy pracují současně
Multithreading (1) • Schopnost programu (za příslušné podpory operačního systému) zavést „multitasking sám v sobě“ • Program se může rozdělit na několik samo-statných výpočtových (prováděcích) vláken, tzv. threads • Jednotlivým vláknům jsou pak opět přidělová-na časová kvanta a tím vzniká dojem, že tato vlákna pracují současně
Multithreading (2) • Dovoluje vyvolat funkci programu, ještě dří-ve než byla dokončena funkce předešlá • Program (v operačním systému podporujícím multithreading) začíná pracovat hlavním (primárním) výpočtovým vláknem • V rámci hlavního výpočtového vlákna mohou být vytvářena a spouštěna další výpočtová vlákna
Třída Thread (1) • Definována ve jmenném prostoru:System.Threading • Umožňuje vytváření a řízení činnosti výpoč-tových vláken • Vytvoření nového výpočtového vlákna lze provést prostřednictvím volání konstruktoru (třídy Thread) • Volanému konstruktoru se jako parametr pře-dá delegát specifikující metodu, která obsa-huje příkazy, jež se budou v průběhu výpoč-tového vlákna provádět
Třída Thread (2) • Delegát specifikující vyvolávanou metodu je tvaru: • public delegate void ThreadStart() • public delegate void ParameterizedThreadStart(object obj) • Zahájení činnosti výpočtového vlákna je mož-né následně provést pomocí volání metody Start: • vlákno je spuštěno asynchronně, tj. jako nebloku-jící • Vlastnosti: • CurrentThread: • vrací aktuálně běžící výpočtové vlákno
Třída Thread (3) • IsBackground: • udává, zda se jedná o výpočtové vlákno, které jena pozadí, tj. background • výpočtové vlákno může být background (nezabraňuje ukončení procesu) nebo foreground • v okamžiku, kdy jsou všechna výpočtová vlákna fore-ground (patřící k danému procesu) ukončena, dojde k ukončení celého procesu a všechna zbývající vlákna background zůstanou nedokončena • Name: • specifikuje jméno výpočtového vlákna • Priority: • udává prioritu vlákna (Lowest, BelowNormal, Normal, AboveNormal, Highest)
Třída Thread (4) • ThreadState: • specifikuje stav vlákna (např. Running, Stopped, Aborted, Background apod.) • Metody: • Abort: • způsobí výjimku ThreadAbortException a za-hájí proces vedoucí k ukončení výpočtového vlákna • výjimka ThreadAbortException může být za-chycena, ale na konci bloku catch je vyvolána znovu • opětovnému vyvolání ThreadAbortException lze zabránit voláním metody ResetAbort • Join: • blokuje volající výpočtové vlákno, dokud dané výpoč-tové vlákno neskončí
Třída Thread (5) • ResetAbort: • ruší požadavek na ukončení výpočtového vlákna • Sleep: • pozastaví provádění vlákna na specifikovaný počet milisekund • Start: • zahájí činnost dříve vytvořeného výpočtového vlákna • dané vlákno se po vyvolání metody Start nachází ve stavu Running • umožňuje předat objekt obsahující data, která mají být použita metodou spouštěnou v rámci výpočtového vlákna • je-li vlákno dokončeno, nemůže být pomocí metody Start znovu restartováno
Třída Thread (6) • Poznámka: • existují i metody Suspend a Resume pro do-časné pozastavení činnosti vlákna a pro opětovné pokračování v jeho činnosti • tyto metody jsou však zastaralé (obsolete) a v bu-doucích verzích nebudou podporovány
Příkaz lock (1) • Označuje blok programu jako kritickou sekci • Slouží k zabezpečení, že určitý blok programu proběhne bez přerušení jinými výpočtovými vlákny • Příklad:privatestatic objecttheLock=newobject();…public static voidDoWork(){lock (theLock){// kritická sekce}}
Příkaz lock (2) • Zaručuje, že výpočtové vlákno nevstoupí do kritické sekce v době, kdy se v ní nachází jiné výpočtové vlákno • Objekt uvedený jako argument za klíčovým slovem lock: • je použitý pro identifikaci zdrojů sdílených mezi více výpočtovými vlákny • musí být viditelný všemi vlákny • musí být referenčního datového typu • by měl být chráněný proti vnějšímu přepsání (private)
Příkaz lock (3) • Příkaz lockpředstavuje syntaktickou zkratku pro volání metod Enter a Exit statické třídy Monitors použitím bloku try a finally • Příklad:privatestatic objecttheLock=newobject();…public static voidDoWork(){Monitor.Enter(theLock);try{// kritická sekce}finally{ Monitor.Exit(theLock); }}
Třída ThreadPool (1) • Definována ve jmenném prostoru System.Threading • Statická třída, která poskytuje fond (sadu) vý-počtových vláken(řízených CLR), která je možné využít k provádění kódu (úloh) • Vhodná zejména pro větší množství kratších úloh • Všechna výpočtová vlákna prováděná v rám-ci třídy ThreadPool: • se chovají jako vlákna background • mají prioritu Normal
Třída ThreadPool (2) • Jestliže vlákno dokončí svou úlohu, je vráce-no do fondu vláken a může být opětovně po-užito: • minimalizuje režii při vytváření nových vláken pro každou úlohu • Jsou-li všechna vlákna zaměstnána, pak jsou další úlohy vkládány do fronty, dokud se ne-uvolní vlákna pro jejich zpracování • Metody: • GetMaxThreads: • vrací maximální počet požadavků, které mohou být současně aktivní
Třída ThreadPool (3) • GetAvailableThreads: • vrací rozdíl mezi maximálním počtem vláken (hodno-tou vrácenou metodou GetMaxThreads) a počtem aktuálně aktivních vláken • SetMaxThreads: • nastavuje maximální počet požadavků, které mohou být současně aktivní • QueueUserWorkItem: • zařazuje metodu, která má být provedena vláknem, do fronty • metoda začne být prováděna v okamžiku, kdy je ve fondu vláken dostupné (volné) vlákno • signatura metody musí odpovídat delegátu:public delegate void WaitCallback(object state)
Třída ThreadPool (4) • RegisterWaitForSingleObject: • registruje tzv. wait handle společně s metodou, která se zavolá v okamžiku, kdy dojde k signalizaci wait handlu • signatura registrované metody musí odpovídat delagá-tu:public delegate void WaitOrTimerCallback(objectstate,bool timedOut) • wait handle lze implementovat pomocí potomků třídy WaitHandle (vyjma třídy Mutex), např. pomocí třídy ManualResetEvent • Pro zjištění, zda vlákno ukončilo svoji čin-nost, je zapotřebí odeslat signál (např. pomo-cí wait handle)
Task Parallel Library • TaskParallelLibrary (TPL) představuje mno-žinu tříd definovanou ve jmenném prostoru System.Threading.Tasks a částečně i ve jmenném prostoru System.Threading • Umožňuje efektivní zpracování úloh s využi-tím všech dostupných jader procesoru • Provádí např. řízení vláken ve fondu vláken (ThreadPool) a další nízkoúrovňové operace • Podobně jako u třídy ThreadPool: • mohou být vlákna opětovně použita • vlákna pracují na pozadí
Třída Parallel (1) • Třída TPL definovaná ve jmenném prostoru System.Threading.Tasks • Automaticky používá vlákna z fondu vláken a řídí konkurenční přístup • Obsahuje (přetěžované) statické metody For a ForEach, které umožňují iterovat kolek-cemi implementujícími rozhraní IEnumerable<T> • Tyto metody: • umožňují zadat část kódu, která má být zpracová-na paralelně • blokují provádění hlavního vlákna
Třída Parallel (2) • Přináší podporu datového paralelismu: • stejné operace jsou prováděny současně nad prv-ky v kolekci (poli) • vstupní kolekce (pole) je rozdělena tak, aby více vláken mohlo současně pracovat nad jejímirůz-nými částmi • Srovnání (foreach): • sekvenční verze: foreach (var item in sCollection){ DoWork(item); } • paralelní ekvivalent: Parallel.ForEach(sCollection, item => DoWork(item));
Třída Parallel (3) • Příklad (možná použití metody For):static voidTestMethod() {Parallel.For(0, 1000, DoWork); Parallel.For(0, 1000, delegate(int i) {// Provedení práce}); Parallel.For(0, 1000, i => {// Provedení práce}); }static voidDoWork(int i) {// Provedení práce}
Třída Task • Definována ve jmenném prostoru System.Threading.Tasks • Reprezentuje asynchronní operace • Metoda, která má být provedena jako samo-statná úloha (task), může být specifikována (jako parametr) v době volání konstruktoru • Její následné spuštění lze realizovat voláním metody Start • Prováděná metoda neblokuje hlavní vlákno aplikace • Na její dokončení počkat pomocí metody Wait