Двата ми цента на SpinLock в .Net

Представете си ситуация, в която нишка се опитва да получи достъп до споделен ресурс, но ресурсът вече е заключен, така че нишката трябва да изчака, докато заключването бъде освободено. Ето къде влиза в сила синхронизацията на нишки. Синхронизацията на нишки се използва, за да се предотврати едновременния достъп на множество нишки до споделен ресурс. Microsoft .Net Framework осигурява поддръжка за редица примитиви за синхронизация, които могат да се използват за контролиране на поведението на нишките и избягване на състезателни условия. Mutex и Spinlock са два популярни механизма за синхронизация, използвани за синхронизиране на достъпа до споделен ресурс.

SpinLock е алтернатива на блокирането на синхронизацията. SpinLock (известен също като "Заето чакане") е механизъм, който може да се използва, за да направи нишка, опитваща се да получи заключване в цикъл, докато не получи достъп до ресурса. Имайте предвид, че SpinLock може да работи по-бързо в сравнение с Mutex, тъй като превключването на контекста е намалено. Трябва обаче да използвате SpinLocks само ако критичната секция трябва да изпълнява минимално количество работа, т.е. SpinLock се задържа за много кратък период от време. SpinLocks обикновено се предпочитат в симетрични мултипроцесорни системи за постоянно анкетиране за наличието на ресурс вместо контекстни превключватели.

Какво е SpinLock и защо е необходим?

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

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

SpinLock обикновено се използват при работа с прекъсвания за извършване на заето изчакване в цикъл, докато ресурсът стане наличен. SpinLock не води до предотвратяване на нишката, а продължава да се върти, докато се освободи заключването на ресурса.

Програмиране на SpinLock в .Net

Обърнете внимание, че SpinLock се дефинира като структура в .Net, т.е. той се определя като тип стойност по съображения за производителност. Следователно, ако прехвърляте екземпляр на SpinLock, трябва да го предадете по препратка, а не по стойност. В този раздел ще проучим как можем да програмираме SpinLock в .Net. За да внедрите SpinLock в .Net, ще трябва да се възползвате от класа SpinLock, наличен в пространството от имена System.Threading.

Следният списък с кодове показва как можете да използвате SpinLock в .Net.

SpinLock spinLock = new SpinLock (true);

bool isLocked = false;

try

{

spinLock.Enter (ref isLocked);

// Write your usual code here

}

finally

{

if (isLocked)

   spinLock.Exit();

}

SpinWait

Имайте предвид, че подобно на SpinLock, SpinWait също е структура, а не клас. Подобно на SpinLock, можете да използвате SpinWait, за да напишете код за синхронизация без заключване, който може да се „върти“, вместо да блокира. SpinWait може да се използва за намаляване на консумацията на ресурси чрез извършване на интензивно въртене на процесора за 10 итерации след което ще даде контрол чрез извикване на Thread.Yield и Thread.Sleep. С други думи, SpinWait може да се използва за ограничаване на CPU-интензивното въртене до фиксиран брой итерации. MSDN гласи: "System.Threading.SpinWait е лек тип синхронизация, който можете да използвате в сценарии на ниско ниво, за да избегнете скъпите превключватели на контекста и преходите на ядрото, необходими за събития в ядрото."

За да използвате SpinWait във вашия код, можете или да използвате статичния метод SpinUntil () на структурата SpinWait, или да се възползвате от неговия нестатичен метод SpinOnce (). Следният кодов фрагмент илюстрира как може да се използва SpinWait.

SpinWait spinWait = new SpinWait();

bool shouldSpin;

while (!shouldSpin)

{

   Thread.MemoryBarrier(); spinWait.SpinOnce();

}