程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#多線程編程中的鎖體系(三)

C#多線程編程中的鎖體系(三)

編輯:C#入門知識

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代碼 這一層,   以後在調內核形式代碼。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved