Vlákna v C# - 6. díl
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Vlákna v C# - 6. dílVlákna v C# - 6. díl

 
Hledat
Moderní platforma pro vytvoření vašeho nového webu – Wix.com.
Nyní už můžete mít web zdarma.
Vybavení pro Laser Game
Spuštěn Filmový magazín

Vlákna v C# - 6. díl

Google       Google       2. 10. 2008       24 123×

Dnes nás čeká poměrně krátká kapitola, a to synchronizační kontexty.

Reklama
Reklama

Kromě manuálního zamykání (jiný způsob locking jsme ani nebrali) můžeme zamykat i deklarativně, automaticky. Docílíme toho tím, že třídu odvodíme od třídy ContextBoundObject a pak na ni aplikujeme atribut Synchronization. Přikážeme tak běhovému prostředí CLR, aby zamykal automaticky:

using System;
using System.Threading;
using System.Runtime.Remoting.Contexts;

[Synchronization]
public class AutoLock : ContextBoundObject
{
    public void Demo()
    {
        Console.Write("Start...");
        Thread.Sleep(1000); // Nestane se, že by se sem dostala dvě vlákna,
        Console.WriteLine("konec"); // díky automatickému lockingu
    }
}

public class Test
{
    public static void Main()
    {
        AutoLock safeInstance = new AutoLock();
        // Zavoláme 3× metodu Demo
        new Thread(safeInstance.Demo).Start();
        new Thread(safeInstance.Demo).Start();
        safeInstance.Demo();
    }
}

CLR zajistí, že jen jedno vlákno může spustit kód uvnitř „safeInstance“. Docílí toho vytvořeným svého synchronizačního objektu, který zamkne okolo každého volání metody nebo vlastnosti ze „safeInstance“. Oblast, kterou zámek dokáže pokrýt, označujeme za synchronizační kontext.

Jak přesně tohle ale celé funguje? Klíč je v v namespace atributu Synchronization, který je System.Runtime.Remoting.Contexts. Instanci ContextBoundObject si můžeme představit jako „vzdálený“ objekt. Tím je myšleno, že všechny volané metody jsou zachyceny. Zachycení probíhá přes „prostředníka“ – když vytvoříme instanci naší třídy AutoLock, CLR vytvoří něco jako prostředníka – objekt se stejnými metodami a vlastnostmi jako AutoLock. Právě přes tohoto prostředníka se vykonává automatické zamykání. Ohledně výkonu – automatické zamykání prodlouží volání metody o pár mikrosekund.

Automatické zamykání nemůže být použito na statické členy (vždy je nutná instance, aby se mohl vytvořit prostředník), ani na třídy, které nejsou odvozené od ContextBoundObject (příkladem budiž Windows formulář odvozený od třídy Form).

Synchronizační kontext může přesáhnout rámec jednoho objektu (instance třídy). Pokud byl synchronizovaný objekt vytvořen z jiné třídy, obě třídy pak sdílejí stejný kontext (jeden velký zámek). Toto chování se dá upravit pomocí nastavení atributu Synchronization přes třídu SynchronizationAttribute (ta obsahuje několik pojmenovaných „int“ konstant, uvedených v tabulce):

Konstanta Význam
NOT_SUPPORTED Totéž, jako když nepoužijeme atribut vůbec
SUPPORTED Spojí existující kontext s právě vytvořeným, pokud žádný další neexistuje, nic se nestane
REQUIRED (výchozí) Spojí existující kontext s právě vytvořeným, pokud žádný další neexistuje, vytvoří se nový
REQUIRES_NEW Vždy vytvoří nový kontext

Takže pokud přes instanci třídy SynchronizaceA vytvoříme instanci třídy SynchronizaceB, oba budou mít svůj vlastní synchronizační kontext (pokud je SynchronizaceB deklarována jako v příkladu níže).

[Synchronization (SynchronizationAttribute.REQUIRES_NEW)]
public class SynchronizaceB : ContextBoundObject {}

Je logické, že čím větší rozsah kontextu, tím je vše snadnější pro správu, ale jsme více omezení možnostmi. Na druhou stranu – při použití hodně kontextů zase hrozí „deadlocky“ (pro připomenutí – zamezení práce dvou vláken navzájem):

[Synchronization]
public class Deadlock : ContextBoundObject
{
    public Deadlock Other;
    public void Demo()
    {
        Thread.Sleep(1000);
        Other.Ahoj();
    }
    void Ahoj()
    {
        Console.WriteLine("ahoj");
    }
}

public class Test
{
    static void Main()
    {
        var dead1 = new Deadlock();
        var dead2 = new Deadlock();
        dead1.Other = dead2;
        dead2.Other = dead1;
        new Thread(dead1.Demo).Start();
        dead2.Demo();
    }
}

Protože je každá instance třídy Deadlock vytvořená uvnitř třídy Test (bez atributu Synchronization), každá instance bude mít svůj synchronizační kontext, a tím pádem i svůj lock. Když se dva objekty různě volají navzájem, jako to dělají v příkladu výše, netrvá dlouho a dojde k deadlocku. Na tento „jev“ je nutné dávat si trochu pozor, u automatického lockingu nemusejí být příčiny vždy tak zřejmé.

Reentrancy

S tímto pojmem jsme se setkali ve třetím díle, označuje metodu, která je absolutně thread-safe – jedno vlákno ji může zavolat hned po zavolání jiným vláknem bez jakýchkoliv neočekávaných efektů atd. Poměrně často mají pojmy „thread-safe“ a „reentrant“ stejný význam.

Avšak nedají se úplně zaměnit. Pravá „reentrant“ metoda vznikne, když atribut Synchronization rozšíříme o klíčové slovo true:

[Synchronization(true)]

Pokud běh aplikace opustí na chvíli ten „svůj“ kontext, dojde k jeho dočasnému zaniknutí. Toto by zabránilo v příkladu nahoře deadlockům! Na druhou stranu, kterékoliv vlákno je pak schopné zavolat kteroukoliv metodu v označené třídě („znovu-vstupovat“ do kontextu; reentering), následkem toho ale mohou být další problémy, kterým se celou tu dobu snažíme vyhnout.

Protože je atribut [Synchronization(true)] aplikován na úrovni třídy, každá metoda v označené třídě se tak stává náchylná na „volné“ volání!

Uvedli jsme si několik příkladů, které ukazují některé nevýhody automatického lockingu. Pokud ho použijeme, můžou vyjít na povrch problémy, které by jindy ani nevznikly. Díky tomu je ve složitějších aplikacích výhradně používané manuální zamykání.

Příště nás čeká téma, které spousta z vás očekává – přístup k prvkům na formuláři pomocí metod Control.Invoke, Control.BeginInvoke a hlavně třídy BackgroundWorker.

Zdroj: http://www.albahari.com/threading/part2.html#_Synchronization_Contexts

×Odeslání článku na tvůj Kindle

Zadej svůj Kindle e-mail a my ti pošleme článek na tvůj Kindle.
Musíš mít povolený příjem obsahu do svého Kindle z naší e-mailové adresy kindle@programujte.com.

E-mailová adresa (např. novak@kindle.com):

TIP: Pokud chceš dostávat naše články každé ráno do svého Kindle, koukni do sekce Články do Kindle.

Hlasování bylo ukončeno    
0 hlasů
Google
(fotka) Jakub KottnauerJakub studuje informatiku na FIT ČVUT, jeho oblíbenou platformou je .NET.
Web     Twitter     Facebook     LinkedIn    

Nové články

Obrázek ke článku První český hackathon ve vlaku inspirovaly služby jako  Tinder, Airbnb nebo Uber

První český hackathon ve vlaku inspirovaly služby jako Tinder, Airbnb nebo Uber

Patnáct set kilometrů, cesta přes dva státy, šestnáct hodin programování a přísun energy drinků, tak by se dal shrnout unikátní hackathon ve vlaku pořádaný Kiwi.com. Z Prahy do Košic a zpět se svezlo celkem 13 týmů, každý s originálním nápadem. Hlavní výhru, voucher na letenky v hodnotě 2 500 EUR, si v Praze převzal tým až z Ukrajiny.

Reklama
Reklama
Obrázek ke článku Gamifikace nakupování dorazila i do České republiky

Gamifikace nakupování dorazila i do České republiky

Zákazníci zejména retailových společností jsou často znuděni klasickými věrnostními či motivačními programy. Většinou z toho důvodu, že jsou jeden jako druhý a nepřináší nic nového. Ale i v České republice se projevují zahraniční trendy, nedávno zde totiž vstoupila na trh a rychle se uchytila nová platforma kombinující to nejlepší z věrnostních a motivačních programů, která navíc využívá prvky gamifikace – Rondo.cz. Na hlavní milníky vývoje nálad a motivace zákazníků a nejnovější trendy se zaměřil Jan Hřebabecký, spoluzakladatel Rondo.cz

Obrázek ke článku NopCommerce – datová vrstva a přístup k datům – 2. díl

NopCommerce – datová vrstva a přístup k datům – 2. díl

V minulém článku jsme si představili platformu NopCommerce z globálního pohledu. V dnešním díle se již zaměříme na konkrétní část systému, a to datovou vrstvu. Představíme si základní stavební kameny systému v podobě doménových objektů. Ukážeme si, jakým způsobem rozšířit doménové objekty a jakým způsobem přistupuje NopCommerce k nastavení systému a modulů.

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032017 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý