Programovanie

Najlepšie postupy pre synchronizáciu vlákien .Net

Synchronizácia je koncept, ktorý sa používa na zabránenie viacerým vláknam v súčasnom prístupe k zdieľanému prostriedku. Môžete ho použiť na zabránenie tomu, aby viaceré vlákna súčasne vyvolávali vlastnosti alebo metódy objektu. Všetko, čo musíte urobiť, je synchronizovať blok kódu, ktorý pristupuje k zdieľanému prostriedku, alebo synchronizovať volania vlastností a členov objektu, aby v danom okamihu mohlo do kritickej sekcie vstúpiť iba jedno vlákno.

Tento článok predstavuje diskusiu o konceptoch týkajúcich sa synchronizácie a bezpečnosti vlákien v .Net a osvedčených postupoch, ktoré sú s tým spojené.

Exkluzívny zámok

Exkluzívne zamykanie sa používa na zabezpečenie toho, že v danom okamihu môže do kritickej sekcie vstúpiť jedno a iba jedno vlákno. Na implementáciu výlučných zámkov vo svojej aplikácii musíte použiť jednu z nasledujúcich možností.

  • Zámok - toto je syntaktická skratka pre statické metódy triedy Monitor a slúži na získanie exkluzívneho zámku pre zdieľaný prostriedok.
  • Mutex - podobné kľúčovému slovu lock okrem toho, že môže fungovať vo viacerých procesoch
  • SpinLock - slúži na získanie exkluzívneho zámku zdieľaného prostriedku tým, že sa vyhne réžii kontextu vlákna

Na implementáciu bezpečnosti vlákien vo svojich aplikáciách môžete použiť statické metódy triedy Monitor alebo kľúčové slovo lock. Statické členy triedy Monitor aj kľúčové slová zámku možno použiť na zabránenie súčasného prístupu k zdieľanému prostriedku. Kľúčové slovo lock je iba skratka na implementáciu synchronizácie. Ak však potrebujete vykonať zložité operácie vo viacvláknovej aplikácii, môžu byť užitočné metódy Wait () a Pulse () triedy Monitor.

Nasledujúci úryvok kódu ilustruje, ako môžete implementovať synchronizáciu pomocou triedy Monitor.

súkromný statický objekt iba na čítanie lockObj = nový objekt ();

       static void Main (reťazec [] args)

        {

Monitor.Enter (lockObj);

                       skús

            {

// Nejaký kód

            }

            konečne

            {

Monitor.Exit (lockObj);

            }

        }

Ekvivalentný kód pomocou kľúčového slova lock bude vyzerať podobne ako tento:

    súkromný statický objekt iba na čítanie lockObj = nový objekt ();

static void Main (reťazec [] args)

        {  

skús

            {

zámok (lockObj)

                {

// Nejaký kód

                }             

            }

konečne

            {

// Tu môžete uvoľniť akékoľvek zdroje

            }

        }

Môžete využiť výhodu triedy Mutex na implementáciu synchronizácie, ktorá sa môže rozprestierať medzi procesmi. Upozorňujeme, že podobne ako v prípade príkazu lock, aj zámok získaný Mutexom sa dá uvoľniť iba z toho istého vlákna, ktoré sa použilo na získanie zámku. Získavanie a uvoľňovanie zámkov pomocou Mutexu je porovnateľne pomalšie ako to isté pomocou príkazu lock.

Hlavnou myšlienkou SpinLocku je minimalizovať náklady spojené s prepínaním kontextu medzi vláknami - ak vlákno môže nejaký čas čakať alebo točiť, kým nezíska zámok na zdieľanom prostriedku, je možné vyhnúť sa réžii spojenej s kontextovým prepínaním medzi vláknami . Keď kritická časť vykoná minimálne množstvo práce, môže to byť dobrý kandidát na SpinLock.

Nevýhradný zámok

Na obmedzenie súbežnosti môžete využiť nevýhradné uzamykanie. Na implementáciu nevýhradných zámkov môžete použiť jednu z nasledujúcich možností.

  • Semafor - slúži na obmedzenie počtu vlákien, ktoré môžu mať prístup k zdieľanému prostriedku súčasne. V podstate sa používa na súčasné obmedzenie počtu spotrebiteľov pre konkrétny zdieľaný zdroj.
  • SemaphoreSlim - rýchla a ľahká alternatíva k triede Semaphore na implementáciu nevýhradných zámkov.
  • ReaderWriterLockSlim - trieda ReaderWriterLockSlim bola predstavená v .Net Framework 3.5 ako náhrada triedy ReaderWriterLock.

Môžete použiť triedu ReaderWriterLockSlim na získanie nevýhradného zámku zdieľaného prostriedku, ktorý by vyžadoval časté čítanie, ale občasné aktualizácie. Takže namiesto vzájomne sa vylučujúceho zámku zdieľaného prostriedku, ktorý vyžaduje časté čítanie a občasné aktualizácie, môžete túto triedu použiť na získanie zámku čítania na zdieľanom prostriedku a výlučného zámku zápisu na ňom.

Zablokovanie

Mali by ste sa vyhnúť použitiu príkazu lock na type alebo použiť príkazy ako lock (this) na implementáciu synchronizácie vo vašej aplikácii, pretože by to mohlo viesť k zablokovaniu. Upozorňujeme, že zablokovanie sa môže vyskytnúť aj vtedy, ak dlhšie držíte zámok získaný na zdieľanom prostriedku. Vo svojich príkazoch zámku by ste nemali používať nemenné typy. Ako príklad by ste sa mali vyhnúť použitiu reťazcového objektu ako kľúča vo vašom vyhlásení o zámke. Mali by ste sa vyhnúť použitiu príkazu lock na verejnom type - je dobrým zvykom uzamknúť súkromné ​​alebo chránené objekty, ktoré nie sú internované. V podstate nastáva situácia zablokovania, keď viac vlákien čaká na seba, aby uvoľnili zámok na zdieľanom prostriedku. Ak sa chcete dozvedieť viac informácií o zablokovaní, môžete si prečítať tento článok na serveri MSDN.

$config[zx-auto] not found$config[zx-overlay] not found