Моите два цента за Mutex и Semaphore в C #

Синхронизацията на нишки се използва, за да се предотврати едновременния достъп на множество нишки до споделен ресурс. Mutex и Semaphore са две от най-важните свързани понятия. Нека разберем какво представляват и двете и кога трябва да ги използваме.

Преди да започнем нашата дискусия, нека да разгледаме набързо основните понятия. Нишката е най-малката единица за изпълнение в процеса. По същество многопоточността ви помага да изпълнявате няколко задачи едновременно и следователно да увеличавате общата производителност на приложението.

Mutex е примитив за синхронизация, който може да работи между процеси - т.е. може да се използва за синхронизация между процеси. Напротив, семафорът е този, който ви позволява да ограничите броя нишки, които имат достъп до споделен ресурс в същия момент от времето. По същество семафорът е по-обобщена форма на мутекс.

Семафор се използва за ограничаване на броя нишки, които могат да имат достъп до споделен ресурс едновременно. По същество се използва за ограничаване на броя на потребителите за даден споделен ресурс едновременно. Можете да се възползвате от Semaphore, за да приложите неизключително заключване и следователно да ограничите едновременността.

Имайте предвид, че Mutex се използва за изключително заключване на споделен ресурс. С други думи, Mutex ви позволява да придобиете взаимно изключващо се заключване - всяка една нишка ще има достъп до споделен ресурс в даден момент от времето. Изключително заключване се използва, за да се гарантира, че във всеки даден момент от време една и само една нишка може да влезе в критичен участък. Критичният раздел може да бъде дефиниран като структура от данни или ресурс, който се споделя от множество нишки, но една и само една нишка може да има достъп до нея във всеки даден момент от времето.

Класът System.Threading.Mutex представлява Mutex, а класът System.Threading.Semaphore се използва за работа със Semaphores. Можете да използвате метода WaitOne на екземпляр от класа Mutex за заключване и да използвате метода ReleaseMutex за отключване.

Mutex mutexObject = new Mutex(false, "Demo");

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

     {

             Console.WriteLine("Quitting for now as another instance is in execution...");

               return;

     }

За да създадете Semaphore в C #, трябва да създадете екземпляр на класа Semaphore. Когато създавате екземпляр на Semaphore, трябва да предадете два аргумента на неговия конструктор на аргументи. Докато първият аргумент се използва за указване на броя на първоначалните записи на ресурс, вторият аргумент се използва за задаване на максималния брой едновременни записи на ресурси. Имайте предвид, че ако искате да запазите всички слотове за новите нишки, които ще бъдат създадени, трябва да посочите еднакви стойности и за двата параметъра. Следният кодов фрагмент илюстрира как можете да създадете семафор в C #.

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

Обърнете се към кодовия фрагмент, даден по-горе. Горното изявление създава семафорен обект с име threadPool, който може да поддържа максимум 5 едновременни заявки. Имайте предвид, че първоначалното броене е зададено на 3, както е посочено в първия параметър на конструктора. Това означава, че 2 слота са запазени за текущата нишка, а 3 слота са налични за други нишки. Нека сега напишем малко код!

Следният кодов фрагмент показва как можете да създадете и стартирате 10 нишки, като използвате класа Thread, наличен в пространството от имена System.Threading. Обърнете внимание как е използван делегатът на ThreadStart.

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

{

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

   threadObject.Name = "Thread Name: " + i;

   threadObject.Start();

}

Ето кода на метода PerformSomeWork. Това е методът, който всъщност съдържа кода за работа със семафори.

private static void PerformSomeWork()

       {

           threadPool.WaitOne();

           Console.WriteLine("Thread {0} is inside the critical section...", Thread.CurrentThread.Name);

           Thread.Sleep(10000);

           threadPool.Release();

       }

Обърнете се към метода PerformSomeWork, даден по-горе. Методът WaitOne се извиква на екземпляра на Semaphore, за да блокира текущата нишка, докато не бъде получен сигнал. Методът Release се извиква на същия екземпляр, за да освободи семафора. Ето пълния списък с кодове за справка.

class SemaphoreDemo

   {

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

       public static void Main(string[] args)

       {

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

           {

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

               threadObject.Name = "Thread Name: " + i;

               threadObject.Start();

           }

           Console.ReadLine();

       }

       private static void PerformSomeWork()

       {

           threadPool.WaitOne();

           Console.WriteLine("Thread {0} is inside the critical section...", Thread.CurrentThread.Name);

           Thread.Sleep(10000);

           threadPool.Release();

       }

   }