Vlákna v C#
Řeší to třída System.Threding
, vlakno = instance tridy Thread
. Staticka vlastnosti Thread.CurrentThread
. Instance ma vlastnost ManagedThreadId
var t = new Thread(delegate ThreadStart());
// to ze vznikne t negarantuje, ze vznikne to actual vlakno, je to spis builder
// t muzeme jeste nastavit nejako vlastnosti
t.Priority = ...
t.IsBackground = true;
t.Start(); // nepusti to vlakno rovnou, jen ho zaradi do planovaciho procesu
Proces té C# aplikace skončí až když doběhnou všechna foreground vlákna. Takže pokud nějaké vlákno nemá brzdit konec aplikace, tak ho nastavim na Background.
Pozor! Context switch je hodně drahý - tisíce taktů procesoru. Pokud v tom jednom bloku co běžím toho počítám málo, tak to může být neefektivní.
Instance .NET vlákna má vlastnosti .Unstarted, .Running a .IsActive. Když už ho OS terminatne, tak má .IsActive == false.
To, že to vlákno je Running neznamená, že něco actually dělá, může čekat na nějaké jiné vlákno. OS přepíná mezi Running a ReadyToRun. Také můžeme udělat thread.Sleep(ms), čímž přejde do stavu Waiting.
thread.Yield() přenese to vlákno do ReadyToRun
Kooperativní plánování - vlákna spolu spolupracují, když se vlákno chce vzdát procesoru, tak zavolá Yeild.
Preemptivní plánování - přepínání řeší OS pomocí nějakého plánovače. Tohle může vést na race condition. Navíc se třeba nějaká datová struktura může rozbít během nějaké interní operace a nechci, aby k tomu v tu dobu mohla přistupovat ostatní vlákna. Pokud je bezpečné mít sdílenou nějakou instanci z různých vláken, tak je thread-safe. Všechny klasické .NET datové struktury (List) NEJSOU thread-safe.
Cekame az dobehne nejake vlakno t
, nechci aktivne cekat pomoci t.IsActive
ani semiaktivne pomoci Thread.Sleep(0)
respektive Thread.Yeild
. Spravne reseni je t.Join()
. Moje vlako se rozbehne, az skonci vlakno t
.
Vlakna bezi v jednom procesu. Kazde vlakno ma vlastni volaci zasobnik, ale vsechny sdili stejnou haldu.