C#多線程編程中的鎖體系(三)。本站提示廣大學習愛好者:(C#多線程編程中的鎖體系(三))文章只能為提供參考,不一定能成為您想要的結果。以下是C#多線程編程中的鎖體系(三)正文
本章重要說下基於內核形式結構的線程同步方法,事宜,旌旗燈號量。
目次
一:實際
二:WaitHandle
三:AutoResetEvent
四:ManualResetEvent
五:總結
一:實際
我們知道線程同步可分為,用戶形式結構和內核形式結構。
內核形式結構:是由windows體系自己應用,內查對象停止調劑協助的。內查對象是體系地址空間中的一個內存塊,由體系創立保護。
內查對象為內核所具有,而不為過程所具有,所以分歧過程可以拜訪統一個內查對象, 如過程,線程,功課,事宜,文件,旌旗燈號量,互斥量等都是內查對象。
而旌旗燈號量,互斥體,事宜是windows專門用來贊助我們停止線程同步的內查對象。
關於線程同步操作來講,內查對象只要2個狀況, 觸發(終止,true)、未觸發(非終止,false)。 未觸發弗成調劑,觸發可調劑。
用戶形式結構:是由特別CPU指令來調和線程,上節講的volatile完成就是一種,Interlocked也是。 也可稱為非壅塞線程同步。
二:WaitHandle
在windows編程中,我們經由過程API創立一個內查對象後會前往一個句柄,句柄則是每一個過程句柄表的索引,爾後可以拿到內查對象的指針、掩碼、標示等。
而WaitHandle籠統基類類感化是包裝了一個windows內查對象的句柄。我們來看下個中一個WaitOne的函數源碼(略精簡)。
public virtual bool WaitOne(TimeSpan timeout)
{
return WaitOne(timeout, false);
}
[System.Security.SecuritySafeCritical] // auto-generated
[SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread-safety.")]
private bool WaitOne(long timeout, bool exitContext)
{
return InternalWaitOne(safeWaitHandle, timeout, hasThreadAffinity, exitContext);
}
[System.Security.SecurityCritical]
internal static bool InternalWaitOne(SafeHandle waitableSafeHandle, long millisecondsTimeout, bool hasThreadAffinity, bool exitContext)
{
Contract.EndContractBlock();
int ret = WaitOneNative(waitableSafeHandle, (uint)millisecondsTimeout, hasThreadAffinity, exitContext);
if (ret == WAIT_ABANDONED)
{
ThrowAbandonedMutexException();
}
return (ret != WaitTimeout);
}
//挪用win32 waitforsingleobjectEx
[System.Security.SecurityCritical]
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern int WaitOneNative(SafeHandle waitableSafeHandle, uint millisecondsTimeout, bool hasThreadAffinity, bool exitContext);
WaitAll 和WaitAny 挪用win32中,waitformultipleobjectsEx函數。
SignalAndWaitOne 挪用win32中,signalandwait函數。
挪用api帶ex都是設置超時的。 假如我們在c#中不傳,默許是-1 表現無窮期期待。
個中SafeWaitHandle字段,包括了一個win32內查對象句柄。
懂得了WaitHandle其他都好辦了,我們來看下它的派生類型。
WaitHandle
|——EventWaitHandle 事宜結構。
|——AutoResetEvent
|——ManualResetEvent
|——Semaphore 旌旗燈號量結構。
|——Mutex 互斥體結構。
個中Semaphore和mutex第一章曾經說過了,上面來看看其他的。
三:AutoResetEvent
應用示例以下,有簡略正文。 關於描寫,盡可能切近體系本身術語。
static void Main(string[] args)
{
//AutoResetEvent example
//AutoResetEvent 告訴正在期待的線程已產生的事宜。
AutoResetEvent waitHandler = new AutoResetEvent(false);//false 即非終止,未觸發。
new Thread(() =>
{
waitHandler.WaitOne(); //壅塞以後線程,期待底層內查對象收到旌旗燈號。
Console.WriteLine("吸收到旌旗燈號,開端處置。");
}).Start();
new Thread(() =>
{
Thread.Sleep(2000);
Console.WriteLine("發旌旗燈號");
waitHandler.Set(); //向內查對象發送旌旗燈號。設置事宜對象為非終止狀況、false,消除壅塞。
}).Start();
//waitHandler.Close(); //釋放句柄資本。
//waitHandler.Reset(); //手動設置事宜為非終止狀況、false,線程阻攔。
Console.ReadLine();
}
WaitOne 壅塞線程,非自旋。
Set() 收回一個旌旗燈號後,設置事宜狀況為false。 這本應當是2步的操作,AutoResetEvent.set()函數,給2步一路主動做了,很便利。
四:ManualResetEvent
這個和下面根本一樣,從字面來講須要手動重置狀況,我們來看例子。
ManualResetEvent manualWaitHandler = new ManualResetEvent(false);//false 即非終止,未觸發。
new Thread(() =>
{
manualWaitHandler.WaitOne(); //壅塞以後線程對象,期待旌旗燈號。
Console.WriteLine("吸收到旌旗燈號,開端處置。");
manualWaitHandler.Reset(); //手動 設置事宜對象狀況為非終止狀況,false。
manualWaitHandler.WaitOne(); //這裡直接壅塞期待有效,由於事宜對象照樣true,必需手動調reset。
Console.WriteLine("第二次吸收到旌旗燈號,開端處置。");
}).Start();
new Thread(() =>
{
Thread.Sleep(2000);
Console.WriteLine("發旌旗燈號");
manualWaitHandler.Set(); //向事宜對象發送ok旌旗燈號。。
Thread.Sleep(2000);
Console.WriteLine("第二次發旌旗燈號");
manualWaitHandler.Set();
}).Start();
Console.ReadLine();
這2則差別很小,實際上是體系Api的辨別,不是net類庫完成的。
在Win32Native類中,我可以看到KERNEL32 api 有這麼個參數isManualReset。
[DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
[ResourceExposure(ResourceScope.Machine)] // Machine or none based on the value of "name"
internal static extern SafeWaitHandle CreateEvent(SECURITY_ATTRIBUTES lpSecurityAttributes, bool isManualReset, bool initialState, String name);
五:總結
基於內核形式結構的同步步調是: 托管代碼->用戶形式代碼->內核形式代碼。
用戶形式結構, 是應用CPU特別指令,停止原子操作。
用戶形式代碼,如圖。 是指 托管代碼挪用 win32代碼 這一層, 以後在調內核形式代碼。