Programování

Moje dva centy na Mutex a Semaphore v C #

Synchronizace vláken se používá k zabránění více vláknům v současném přístupu ke sdílenému prostředku. Mutex a Semaphore jsou dva z nejdůležitějších souvisejících konceptů. Pojďme pochopit, co to je a kdy bychom je měli použít.

Než zahájíme diskusi, pojďme se rychle podívat na základní pojmy. Vlákno je nejmenší jednotka provedení v rámci procesu. Multi-threading v zásadě pomáhá provádět několik úkolů současně, a tím zvyšuje celkovou propustnost aplikace.

Mutex je synchronizační primitiv, který může pracovat napříč procesy - tj. Může být použit pro synchronizaci mezi procesy. Semafor naopak je ten, který umožňuje omezit počet vláken, která mají přístup ke sdílenému prostředku ve stejném okamžiku. V podstatě je semafor obecnější formou Mutexu.

Semafor se používá k omezení počtu vláken, která mohou mít současně přístup ke sdílenému prostředku. V podstatě se používá k současnému omezení počtu spotřebitelů pro konkrétní sdílený prostředek. Semaphore můžete využít k implementaci nevýhradního zamykání, a tedy k omezení souběžnosti.

Všimněte si, že Mutex se používá pro výlučné uzamčení sdíleného prostředku. Jinými slovy, Mutex vám umožňuje získat vzájemně se vylučující zámek - jakékoli vlákno by mělo v daném okamžiku přístup ke sdílenému prostředku. Exkluzivní zamykání se používá k zajištění toho, že v daném okamžiku může do kritické sekce vstoupit jedno a pouze jedno vlákno. Kritická část může být definována jako datová struktura nebo prostředek, který je sdílen více vlákny, ale jedno a pouze jedno vlákno k němu může mít přístup v daném okamžiku.

Třída System.Threading.Mutex představuje Mutex a pro práci se Semaphores se používá třída System.Threading.Semaphore. Můžete použít WaitOne metodu na instanci třídy Mutex k uzamčení a použití metody ReleaseMutex k odemčení.

Mutex mutexObject = nový Mutex (false, "Demo");

if (! mutexObject.WaitOne (TimeSpan.FromSeconds (10), false))

     {

Console.WriteLine ("Ukončuji zatím, protože se provádí jiná instance ...");

vrátit se;

     }

Chcete-li vytvořit Semaphore v C #, měli byste vytvořit instanci třídy Semaphore. Při vytváření instance Semaphore musíte předat dva argumenty jejímu konstruktoru argumentů. Zatímco první argument se používá k označení počtu počátečních položek prostředků, druhý argument se používá k určení maximálního počtu souběžných položek prostředků. Všimněte si, že pokud chcete rezervovat všechny sloty pro nová vlákna, která by byla vytvořena, měli byste zadat stejné hodnoty pro oba tyto parametry. Následující fragment kódu ukazuje, jak můžete vytvořit semafor v C #.

public static Semaphore threadPool = new Semaphore (3, 5);

Viz výše uvedený fragment kódu. Výše uvedený příkaz vytvoří semaforový objekt s názvem threadPool, který může podporovat maximálně 5 souběžných požadavků. Všimněte si, že počáteční počet je nastaven na 3, jak je uvedeno v prvním parametru konstruktoru. To znamená, že 2 sloty jsou rezervovány pro aktuální vlákno a 3 sloty jsou k dispozici pro další vlákna. Pojďme nyní napsat nějaký kód!

Následující fragment kódu ukazuje, jak můžete vytvořit a spustit 10 vláken pomocí třídy Thread dostupné ve jmenném prostoru System.Threading. Všimněte si, jak byl použit delegát ThreadStart.

pro (int i = 0; i <10; i ++)

{

Thread threadObject = new Thread (new ThreadStart (PerformSomeWork));

threadObject.Name = "Název vlákna:" + i;

threadObject.Start ();

}

Tady je kód metody PerformSomeWork. Toto je metoda, která ve skutečnosti obsahuje kód pro práci se semafory.

private static void PerformSomeWork ()

       {

threadPool.WaitOne ();

Console.WriteLine ("Vlákno {0} je uvnitř kritické sekce ...", Thread.CurrentThread.Name);

Thread.Sleep (10 000);

threadPool.Release ();

       }

Viz výše uvedená metoda PerformSomeWork. WaitOne metoda je volána na instanci Semaphore k zablokování aktuálního vlákna, dokud není přijat signál. Release metoda je volána ve stejné instanci k uvolnění semaforu. Zde je kompletní seznam kódů pro vaši referenci.

třída SemaphoreDemo

   {

public static Semaphore threadPool = new Semaphore (3, 5);

public static void Main (řetězec [] args)

       {

pro (int i = 0; i <10; i ++)

           {

Thread threadObject = new Thread (new ThreadStart (PerformSomeWork));

threadObject.Name = "Název vlákna:" + i;

threadObject.Start ();

           }

Console.ReadLine ();

       }

private static void PerformSomeWork ()

       {

threadPool.WaitOne ();

Console.WriteLine ("Vlákno {0} je uvnitř kritické sekce ...", Thread.CurrentThread.Name);

Thread.Sleep (10 000);

threadPool.Release ();

       }

   }