Lekce 1 - Vlákna - Úvod do vícevláknových aplikací v C# .NET
Vítejte v první lekci kurzu zaměřeného na programování
vícevláknových aplikací v C# .NET. Vysvětlíme si pojmy
jako proces, vlákna a jejich
synchronizace. Práci s vláknem si zkusíme na třídě
Thread
z .NET.
Naučíme se plně využívat moderních vícejádrových
procesorů a spouštět úlohy na pozadí, které by
jinak mohly zablokovat hlavní vlákno aplikace. Dále se budeme zabývat
nejnovějšími technologiemi z .NET frameworku, včetně paralelního
programování, úloh a klíčových slov async
a
await
.
Požadavky na znalosti
Pro dokončení celého kurzu se předpokládají znalosti v tomto rozsahu:
- Základní konstrukce jazyka C# .NET,
- Objektově orientované programování v C# .NET,
- Kolekce a LINQ v C# .NET.
Úvod do teorie vláken
Než začneme používat vlákna, popišme si, jakým způsobem aplikace spouští náš operační systém. Windows je víceúlohový operační systém (multitasking). Jak již název napovídá, multitasking znamená provádění více úkolů současně. Například na svém počítači můžeme současně otevřít prohlížeč Google Chrome, dokument Microsoft Word, Poznámkový blok, VLC Media Player, Visual Studio atd.
Multitasking tedy znamená souběžné provádění více úkolů nebo procesů v počítačovém systému. Umožňuje počítači vypadat, jako by prováděl více úkolů současně, i když má obvykle jednu centrální procesorovou jednotku (CPU). Multitasking je základní funkcí moderních operačních systémů a hraje důležitou roli při zlepšování efektivity, odezvy a použitelnosti počítačů.
Principy Multitaskingu a přepínání aplikací
Windows efektivně řídí spouštěné aplikace pomocí tak zvaného scheduleru, který se podílí na tak zvaném timeslicingu. Jednoduše řečeno, systém rychle přepíná mezi spuštěnými aplikacemi. Když jednu zastaví, spustí na okamžik jinou. Pro uživatele to vypadá, jako by všechny aplikace běžely souběžně, ačkoliv ve skutečnosti dochází k rychlému střídání mezi nimi.
S nástupem vícejádrových procesorů se tato zásada nezměnila. Windows stále přepíná mezi aplikacemi, ale s tím rozdílem, že nyní dokáže vykonávat několik instrukcí najednou na každém procesorovém jádru. Vícejádrové procesory umožňují individuálním vláknům běžet současně na různých jádrech, což výrazně zvyšuje výkon a efektivitu systému.
Takto jsou aplikace schopny využít moderní hardware a efektivněji spolupracovat s vícejádrovými procesory.
Aplikace, proces, vlákno a synchronizace
Zamysleme se nad termíny aplikace, proces a vlákno. Aplikaci si jistě dokážeme představit, je to například internetový prohlížeč, ve kterém čteme tento článek. Co je ovšem proces a co vlákno?
Proces
V operačním systému je proces základním konceptem reprezentujícím spuštěný program. Je to nejmenší jednotka práce v provádění počítačového systému. Každý proces má svůj vlastní paměťový prostor, který obsahuje programový kód, data a zásobník pro správu volání funkcí a lokálních proměnných. Operační systém spravuje procesy a má své vlastní zdroje, jako je čas procesoru, popisovače souborů a informace o stavu systému.
Pokud si spustíme 3x kalkulačku, nalezneme ve správci úloh 3x proces
calc.exe
. Některé složitější aplikace mohou využívat
několik procesů, například Google Chrome vytvoří proces pro každou
otevřenou záložku. Většinou mají aplikace však jen jeden proces:
Vlákno
V operačním systému je vlákno menší jednotkou provádění v rámci procesu. Vlákna se někdy nazývají odlehčené procesy, protože sdílejí stejný paměťový prostor jako nadřazený proces, včetně jeho kódu, dat a prostředků. Vlákna však mají svůj vlastní kontext provádění, včetně čítače programu, registrů a zásobníku. Vlákna v rámci stejného procesu mohou běžet souběžně, což umožňuje paralelní provádění úloh.
Ve výchozím nastavení má každý proces alespoň jedno vlákno, které je odpovědné za provádění kódu aplikace. Toto vlákno se nazývá hlavní vlákno. Každá aplikace je tedy standardně jednovláknová.
Synchronizace
Synchronizace hraje klíčovou roli při manipulaci s více vlákny. Když několik vláken provádí operace na jednom objektu, je nezbytné zajistit synchronizaci přístupu k tomuto objektu. Toto opatření předejde konfliktům a udrží konzistentní stav objektu. V prostředí .NET máme k dispozici různé strategie synchronizace:
- Třídu
Monitor
. - Manuální synchronizaci – Použití synchronizačních objektů poskytované knihovnou tříd .NET.
- Synchronizované kontexty – Pouze pro aplikace .NET
Framework a Xamarin využívající
SynchronizationAttribute
pro jednoduchou automatickou synchronizaci. - Kolekci
System.Collections.Concurrent
– Tyto třídy poskytují vestavěné synchronizované operace přidávání a odebírání.
Bez synchronizace by jedno vlákno mohlo přerušit činnost druhého, což by mohlo způsobit neplatný stav objektu. Třída, jejíž členové jsou chráněni před takovými přerušeními, se označuje jako thread-safe.
Proč synchronizovat vlákna
Představme si, že máme jednoduchou bankovní aplikaci, která obsahuje účet se zůstatkem. Nyní si představme dvě vlákna, která se snaží na tomto účtu provádět operace:
- Jedno vlákno chce přidat peníze (například vložit mzdu).
- Druhé vlákno chce odebrat peníze (například provedení výběru).
Bez synchronizace by obě vlákna mohla současně přistoupit k účtu a manipulovat s jeho hodnotou, což by vedlo k nekonzistentním datům.
Vlákno v .NET
V .NET lze vytvářet vlákna pomocí třídy Thread
z jmenných
prostorů System.Threading
. Instanci třídy Thread
a
přiřazení metody, která bude prováděna ve vlákně, bychom napsali
takto:
Thread vlakno = new Thread(MetodaVlakna);
Metodou Start()
bychom spustili nové vlákno a zahájili
provedení přiřazené metody:
vlakno.Start();
Vlastnosti třídy Thread
Zatím pro nás budou důležité pouze tyto vlastnosti na třídě
Thread
:
isAlive
– Vrací hodnotutrue
, pokud bylo vlákno spuštěno a dosud nebylo normálně ukončeno nebo přerušeno.IsBackground
– Získá nebo nastaví logickou hodnotu, která označuje, zda je vlákno vláknem na pozadí.Name
– Získá nebo nastaví název vlákna.Priority
– Získá nebo nastaví prioritu plánování vláken operačním systémem.ThreadState
– Získá hodnotu obsahující aktuální stavy vlákna.
V příští lekci, Vlákna - Příklady vícevláknových aplikací v C# .NET, si vyzkoušíme naprogramovat dvě vícevláknové aplikace, ve kterých se naučíme vlákna zakládat, pojmenovat a spouštět.