.Net基于Thread實現(xiàn)自旋鎖的三種方式

基于Thread.SpinWait實現(xiàn)自旋鎖
實現(xiàn)原理:基于Test--And--Set原子操作實現(xiàn)
使用一個數(shù)據(jù)表示當(dāng)前鎖是否已經(jīng)被獲取 0表示未被索取,1表示已經(jīng)獲取 獲取鎖時會將_lock的值設(shè)置為1 然后檢查修改前的值是否等于0,
優(yōu)點:
- 不使用Thread.SpinWait方法,重試的方法體會為空,CPU會使用它的最大性能來不斷的進行賦值和比較指令,會浪費很大的性能,Thread.SpinWait提示CPU當(dāng)前正在自旋鎖的循環(huán)中,可以休息若干個時間周期
- 使用自旋鎖需要注意的問題,自旋鎖保護的代碼應(yīng)該在非常短的時間內(nèi)執(zhí)行完成,如果時間過長,其他線程不斷重試導(dǎo)致影響其他線程進行
缺點:
當(dāng)前實現(xiàn)沒有考慮到公平性,如果多個線程同時獲取鎖失敗,按時間順序第一個獲取鎖的線程不一定會在釋放鎖后第一個獲取成功,
代碼實現(xiàn):
public static class ThreadSpinWaitDemo
{
private static int _lock = 0;
private static int _counterA = 0;
private static int _counterB = 0;
public static void IncrementCounters()
{
while (Interlocked.Exchange(ref _lock, 1) != 0)
{
Thread.SpinWait(1);
}
++_counterA;
++_counterB;
Interlocked.Exchange(ref _lock, 0);
}
public static void GetCounters(out int counterA, out int counterB)
{
while (Interlocked.Exchange(ref _lock, 1) != 0)
{
Thread.SpinWait(1);
}
counterA = _counterA;
counterB = _counterB;
Interlocked.Exchange(ref _lock, 0);
}
}
基于SpinWaite實現(xiàn)自旋鎖
特性是SpinOnce方法的次數(shù),如果在一定次數(shù)以內(nèi)并且當(dāng)前邏輯核心所大于1,則調(diào)用Thread.SpinWait函數(shù);如果超過一定次數(shù)或者當(dāng)前環(huán)境邏輯核心數(shù)等于1,則交替使用
Thread.Sleep(0)和Thread.Yield函數(shù),表示切換到其他線程,如果再超過一定次數(shù),則讓當(dāng)前線程休眠
SpinWaite解決Thread.SpinWait中的兩個問題
- 如果自旋鎖運行時間超長,SpinWaite可以提示操作系統(tǒng)切換到其他線程或者讓當(dāng)前線程進入休眠狀態(tài),
- 如果當(dāng)前環(huán)境只有一個核心邏輯,SpinWaite不會執(zhí)行Thread.SpinWait函數(shù),而是直接提示操作系統(tǒng)切換到其他線程,
public static class ThreadSpinOnceDemo
{
private static int _lock = 0;
private static int _counterA = 0;
private static int _counterB = 0;
public static void IncrementCounters()
{
var spinWait = new SpinWait();
while (Interlocked.Exchange(ref _lock, 1) != 0)
{
spinWait.SpinOnce();
}
++_counterA;
++_counterB;
Interlocked.Exchange(ref _lock, 0);
}
public static void GetCounters(out int counterA, out int counterB)
{
var spinWait = new SpinWait();
while (Interlocked.Exchange(ref _lock, 1) != 0)
{
spinWait.SpinOnce();
}
counterA = _counterA;
counterB = _counterB;
Interlocked.Exchange(ref _lock, 0);
}
}
基于SpinLock實現(xiàn)自旋鎖
封裝了SpinWaite的邏輯
SpinLock代碼實現(xiàn)
public class ThreadSpinLockDemo
{
private static SpinLock _spinLock = new SpinLock();
private static int _counterA = 0;
private static int _counterB = 0;
public static void IncrementCounters()
{
bool lockTaken = false;
try
{
_spinLock.Enter(ref lockTaken);
++_counterA;
++_counterB;
}
finally
{
if (lockTaken)
{
_spinLock.Exit();
}
}
}
public static void GetCounters(out int counterA, out int counterB)
{
bool lockTaken = false;
try
{
_spinLock.Enter(ref lockTaken);
counterA = _counterA;
counterB = _counterB;
}
finally
{
if (lockTaken)
{
_spinLock.Exit();
}
}
}
}
簡述 Thread.Sleep(0)和Thread.Yield的區(qū)別
- 在Windows系統(tǒng)中 Thread.Sleep調(diào)用系統(tǒng)提供的SleepEx函數(shù),Thread.Yield函數(shù)調(diào)用的是系統(tǒng)提供的SwitchToThread方法,
- 區(qū)別在于SwitchToThread函數(shù)只會切換到當(dāng)前核心邏輯關(guān)聯(lián)的待運行隊列的線程,不會切換到其他核心邏輯關(guān)聯(lián)的線程上,而SleepEx函數(shù)會切換到任意邏輯核心關(guān)聯(lián)的待運行隊列中的線程,并且讓當(dāng)前線程在指定時間內(nèi)無法重新進入待運行隊列(如果線程為0 那么線程可以立刻重新進入待運行隊列)
- 在Linux和OSX中 Thread.Sleep函數(shù)在休眠時間不為0時會調(diào)用pthread類庫提供的pthread_cond_timedWait函數(shù),在休眠時間為0時會調(diào)用sched_yield函數(shù),Thread.Yield同樣會調(diào)用sched_yield函數(shù) sched_yield在windows和osx系統(tǒng)中沒有區(qū)別,都只會切換到當(dāng)前和邏輯核心關(guān)心的待運行隊列中的線程,不會切換到其他核心邏輯關(guān)聯(lián)的線程上。在unix系統(tǒng)上調(diào)用系統(tǒng)提供的sleep函數(shù)并傳入0 會直接忽略返回
以上就是.Net基于Thread實現(xiàn)自旋鎖的三種方式的詳細內(nèi)容,更多關(guān)于.Net自旋鎖的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
ASP.NET中DropDownList和ListBox實現(xiàn)兩級聯(lián)動功能
這篇文章主要介紹了ASP.NET中DropDownList和ListBox實現(xiàn)兩級聯(lián)動功能的相關(guān)資料,需要的朋友可以參考下2016-01-01
詳解使用DotNet CLI創(chuàng)建自定義的WPF項目模板
這篇文章主要介紹了詳解使用DotNet CLI創(chuàng)建自定義的WPF項目模板,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-04-04
MVC使用T4模板生成其他類的具體實現(xiàn)學(xué)習(xí)筆記2
這篇文章主要為大家詳細介紹了MVC使用T4模板生成其他類的具體實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-09-09
擴展 Entity Framework支持復(fù)雜的過濾條件(多個關(guān)鍵字模糊匹配)
之前遇到一個棘手的Linq to EF查詢的技術(shù)問題,現(xiàn)有產(chǎn)品表Product,需要根據(jù)多個關(guān)鍵字模糊匹配產(chǎn)品名稱, 現(xiàn)將解決方案分享出來,按興趣的朋友可以參考下2012-12-12
詳解在Windows下如何使用AspNetCore Api 和consul
這篇文章主要介紹了詳解在Windows下如何使用AspNetCore Api 和consul,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06

