亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

C#多線程編程中的鎖系統基本用法

2020-01-24 02:00:53
字體:
來源:轉載
供稿:網友

平常在多線程開發中,總避免不了線程同步。本篇就對net多線程中的鎖系統做個簡單描述。

目錄
一:lock、Monitor
     1:基礎。
     2: 作用域。
     3:字符串鎖。
     4:monitor使用
二:mutex
三:Semaphore
四:總結

一:lock、Monitor

1:基礎

Lock是Monitor語法糖簡化寫法。Lock在IL會生成Monitor。

復制代碼 代碼如下:

//======Example 1=====
            string obj = "helloworld";
            lock (obj)
            {
                Console.WriteLine(obj);
            }
            //lock  IL會編譯成如下寫法
            bool isGetLock = false;
            Monitor.Enter(obj, ref isGetLock);
            try
            {
                Console.WriteLine(obj);
            }
            finally
            {
                if (isGetLock)
                {
                    Monitor.Exit(obj);
                }
            }

isGetLock參數是Framework  4.0后新加的。 為了使程序在所有情況下都能夠確定,是否有必要釋放鎖。例: Monitor.Enter拿不到鎖

Monitor.Enter 是可以鎖值類型的。鎖時會裝箱成新對象,所以無法做到線程同步。

2:作用域

     一:Lock是只能在進程內鎖,不能跨進程。走的是混合構造,先自旋再轉成內核構造。

     二:關于對type類型的鎖。如下:

復制代碼 代碼如下:

//======Example 2=====
            new Thread(new ThreadStart(() => {
                lock (typeof(int))
                {
                    Thread.Sleep(10000);
                    Console.WriteLine("Thread1釋放");
                }
            })).Start();
            Thread.Sleep(1000);
            lock(typeof(int))
            {
                Console.WriteLine("Thread2釋放");
            }

運行結果如下:

我們在來看個例子。

復制代碼 代碼如下:

//======Example 3=====
            Console.WriteLine(DateTime.Now);
            AppDomain appDomain1 = AppDomain.CreateDomain("AppDomain1");
            LockTest Worker1 = (LockTest)appDomain1.CreateInstanceAndUnwrap(
             Assembly.GetExecutingAssembly().FullName,
             "ConsoleApplication1.LockTest");
            Worker1.Run();

            AppDomain appDomain2 = AppDomain.CreateDomain("AppDomain2");
            LockTest Worker2 = (LockTest)appDomain2.CreateInstanceAndUnwrap(
            Assembly.GetExecutingAssembly().FullName,
            "ConsoleApplication1.LockTest");
            Worker2.Run();
/// <summary>
    /// 跨應用程序域邊界或遠程訪問時需要繼承MarshalByRefObject
    /// </summary>
    public class LockTest : MarshalByRefObject
    {
        public void Run()
        {
            lock (typeof(int))
            {
                Thread.Sleep(10000);
                Console.WriteLine(AppDomain.CurrentDomain.FriendlyName + ": Thread 釋放," + DateTime.Now);
            }
        }
    }

運行結果如下:

第一個例子說明,在同進程同域,不同線程下,鎖type int,其實鎖的是同一個int對象。所以要慎用。

第二個例子,這里就簡單說下。

      A: CLR啟動時,會創建 系統域(System Domain)和共享域(Shared Domain), 默認程序域(Default AppDomain)。 系統域和共享域是單例的。程序域可以有多個,例子中我們使用AppDomain.CreateDomain方法創建的。

      B:  按正常來說,每個程序域的代碼都是隔離,互不影響的。但對于一些基礎類型來說,每個程序域都重新加載一份,就顯得有點浪費,帶來額外的損耗壓力。聰明的CLR會把一些基本類型Object, ValueType, Array, Enum, String, and Delegate等所在的程序集MSCorLib.dll,在CLR啟動過程中都會加載到共享域。  每個程序域都會使用共享域的基礎類型實例。 

      C: 而每個程序域都有屬于自己的托管堆。托管堆中最重要的是GC heap和Loader heap。GC heap用于引用類型實例的存儲,生命周期管理和垃圾回收。Loader heap保存類型系統,如MethodTable,數據結構等,Loader heap生命周期不受GC管理,跟程序域卸載有關。

     所以共享域中Loader heap MSCorLib.dll中的int實例會一直保留著,直到進程結束。單個程序域卸載也不受影響。作用域很大有沒有!??!

     這時第二個例子也很容易理解了。 鎖int實例是跨程序域的,MSCorLib中的基礎類型都是這樣。 極容易造成死鎖,慎用。  而自定義類型則會加載到自己的程序域,不會影響別人。

3:字符串的鎖

我們都知道鎖的目的,是為了多線程下值被破壞。也知道string在c#是個特殊對象,值是不變的,每次變動都是一個新對象值,這也是推薦stringbuilder原因。如例:

復制代碼 代碼如下:

//======Example 4=====
        string str1 = "mushroom";
        string str2 = "mushroom";
        var result1 = object.ReferenceEquals(str1, str2);
        var result2 = object.ReferenceEquals(str1, "mushroom");
        Console.WriteLine(result1 + "-" + result2);
        /* output
         * True-True
         */

 正式由于c#中字符串的這種特性,所以字符串是在多線程下是不會被修改的,只讀的。它存在于SystemDomain域中managed heap中的一個hash table中。Key為string本身,Value為string對象的地址。

 當程序域需要一個string的時候,CLR首先在這個Hashtable根據這個string的hash code試著找對應的Item。如果成功找到,則直接把對應的引用返回,否則就在SystemDomain對應的managed heap中創建該 string,并加入到hash table中,并把引用返回。所以說字符串的生命周期是基于整個進程的,也是跨AppDomain。

4:monitor用法

介紹下Wait,Pulse,PulseAll的用法。有注釋,大家直接看代碼吧。

復制代碼 代碼如下:

static string str = "mushroom";
        static void Main(string[] args)
        {
            new Thread(() =>
            {
                bool isGetLock = false;
                Monitor.Enter(str, ref isGetLock);
                try
                {
                    Console.WriteLine("Thread1第一次獲取鎖");
                    Thread.Sleep(5000);
                    Console.WriteLine("Thread1暫時釋放鎖,并等待其他線程釋放通知信號。");
                    Monitor.Wait(str);
                    Console.WriteLine("Thread1接到通知,第二次獲取鎖。");
                    Thread.Sleep(1000);
                }
                finally
                {
                    if (isGetLock)
                    {
                        Monitor.Exit(str);
                        Console.WriteLine("Thread1釋放鎖");
                    }
                }
            }).Start();
            Thread.Sleep(1000);
            new Thread(() =>
            {
                bool isGetLock = false;
                Monitor.Enter(str, ref isGetLock); //一直等待中,直到其他釋放。
                try
                {
                    Console.WriteLine("Thread2獲得鎖");
                    Thread.Sleep(5000);
                    Monitor.Pulse(str); //通知隊列里一個線程,改變鎖狀態。  Pulseall 通知所有的
                    Console.WriteLine("Thread2通知其他線程,改變狀態。");
                    Thread.Sleep(1000);
                }
                finally
                {
                    if (isGetLock)
                    {
                        Monitor.Exit(str);
                        Console.WriteLine("Thread2釋放鎖");
                    }
                }

            }).Start();
            Console.ReadLine();

二:mutex

 lock是不能跨進程鎖的。 mutex作用和lock類似,但是它能跨進程鎖資源(走的是windows內核構造)。 我們來看個例子
 

復制代碼 代碼如下:

 static bool createNew = false;
        //第一個參數 是否應擁有互斥體的初始所屬權。即createNew true時,mutex默認獲得處理信號
        //第二個是名字,第三個是否成功。
        public static Mutex mutex = new Mutex(true, "mushroom.mutex", out createNew);

        static void Main(string[] args)
        {
            //======Example 5=====
            if (createNew)  //第一個創建成功,這時候已經拿到鎖了。 無需再WaitOne了。一定要注意。
            {
                try
                {
                    Run();
                }
                finally
                {
                    mutex.ReleaseMutex(); //釋放當前鎖。 
                }
            }
            //WaitOne 函數作用是阻止當前線程,直到拿到收到其他實例釋放的處理信號。
            //第一個參數是等待超時時間,第二個是否退出上下文同步域。
            else if (mutex.WaitOne(10000,false))//
            {
                try
                {
                    Run();
                }
                finally
                {
                    mutex.ReleaseMutex();
                }
            }
            else//如果沒有發現處理信號
            {
                Console.WriteLine("已經有實例了。");
                Console.ReadLine();
            }
        }
        static void Run()
        {
            Console.WriteLine("實例1");
            Console.ReadLine();
        }
 

 我們順序起A  B實例測試下。   A首先拿到鎖,輸出 實例1 。   B在等待, 如果10秒內A釋放,B拿到執行Run()。  超時后輸出  已經有實例了。

這里注意的是第一個拿到處理信號 的實例,已經拿到鎖了。不需要再WaitOne。  否則報異常。 

三:Semaphore

 即信號量,我們可以把它理解為升級版的mutex。mutex對一個資源進行鎖,semaphore則是對多個資源進行加鎖。

semaphore是由windows內核維持一個int32變量的線程計數器,線程每調用一次、計數器減一、釋放后對應加一, 超出的線程則排隊等候。

走的是內核構造,所以semaphore也是可以跨進程的。

復制代碼 代碼如下:

static void Main(string[] args)
        {
            Console.WriteLine("準備處理隊列");

            bool createNew = false;

            SemaphoreSecurity ss = new SemaphoreSecurity(); //信號量權限控制
            Semaphore semaphore = new Semaphore(2, 2, "mushroom.Semaphore", out createNew,null);
            for (int i = 1; i <= 5; i++)
            {
                new Thread((arg) =>
                {
                    semaphore.WaitOne();
                    Console.WriteLine(arg + "處理中");
                    Thread.Sleep(10000);
                    semaphore.Release(); //即semaphore.Release(1)
                    //semaphore.Release(5);可以釋放多個,但不能超過最大值。如果最后釋放的總量超過本身總量,也會報錯。 不建議使用

                }).Start(i);
            }
            Console.ReadLine();
        }

四:總結

 mutex、Semaphore  需要由托管代碼轉成本地用戶模式代碼、再轉換為本地內核代碼。 

 反之同樣,饒了一大圈,性能肯定不會很好。所以僅在需要跨進程的場景才使用。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久亚洲综合国产精品99麻豆精品福利| 亚洲影院色无极综合| 亚洲精品av在线播放| 日本亚洲欧洲色α| 亚洲色图av在线| 欧美高清无遮挡| 国产成人免费av电影| 国产女人18毛片水18精品| 国产一区二区三区毛片| 日韩成人小视频| 亚洲国产精品va| 国产欧美va欧美va香蕉在线| 欧美日韩美女在线| 国产精品一区二区三区毛片淫片| 国产精品久久久999| 成人性教育视频在线观看| 亚洲精品国产精品乱码不99按摩| 欧美日韩国产精品一区二区三区四区| 亚洲国产精品免费| 欧美精品在线播放| 成人网欧美在线视频| 日韩av综合网| 国语自产精品视频在免费| 国产精品对白刺激| 日韩欧美精品免费在线| 国产乱人伦真实精品视频| 国产色婷婷国产综合在线理论片a| 亚洲成人亚洲激情| 亚洲最大在线视频| 久久久人成影片一区二区三区观看| 欧美日韩高清区| 欧美午夜片在线免费观看| 最近的2019中文字幕免费一页| 亚洲人线精品午夜| 俺也去精品视频在线观看| 伊人亚洲福利一区二区三区| 欧美国产视频日韩| 国产免费一区视频观看免费| 欧美日韩国产精品一区二区不卡中文| 欧美亚洲另类在线| 久久99精品久久久久久噜噜| 欧美日韩一区二区精品| 国产精品pans私拍| 成人有码视频在线播放| 国产精品jizz在线观看麻豆| 91精品视频在线播放| 国产欧美日韩免费看aⅴ视频| 国产免费一区二区三区香蕉精| 一区二区三区高清国产| 色综合久久精品亚洲国产| 日本最新高清不卡中文字幕| 91精品国产综合久久香蕉922| 亚洲精品在线观看www| 亚洲一级一级97网| 中文字幕在线成人| 久久综合亚洲社区| 欧美大片欧美激情性色a∨久久| 亚洲国产精久久久久久| 色香阁99久久精品久久久| 久久国产精品影视| 国产美女高潮久久白浆| 亚洲综合大片69999| 久久久久久久久久久久久久久久久久av| 136fldh精品导航福利| 欧美久久精品一级黑人c片| 亚洲在线免费看| 亚洲欧洲一区二区三区久久| 亚洲人成电影在线播放| 欧美黄色片免费观看| 国产精品三级美女白浆呻吟| 亚洲福利精品在线| 97av在线影院| 在线日韩中文字幕| 国产网站欧美日韩免费精品在线观看| 亚洲精品之草原avav久久| 亚州av一区二区| 成人黄色av网| 亚洲免费高清视频| 国产啪精品视频网站| 亚洲毛片在线观看.| 2020久久国产精品| 日韩影视在线观看| 国产精品自拍视频| 久久久爽爽爽美女图片| 欧美激情欧美狂野欧美精品| 在线播放日韩专区| 欧美视频中文字幕在线| 在线性视频日韩欧美| 久久久精品视频成人| 国产精品你懂得| 91国内在线视频| 亚洲区一区二区| 精品女同一区二区三区在线播放| 欧美电影免费观看| 精品免费在线视频| 日韩欧美一区二区三区久久| 国产盗摄xxxx视频xxx69| 国产成人福利视频| 国产精品视频自在线| 国产精品成久久久久三级| 福利视频一区二区| 久久久综合av| 亚洲国产精品视频在线观看| 国产精品白嫩初高中害羞小美女| 成人国内精品久久久久一区| 欧美在线日韩在线| 亚洲视频欧洲视频| 91精品国产高清自在线| 日韩精品免费在线观看| 欧美成人免费一级人片100| 亚洲国产精久久久久久久| 欧美精品在线观看91| 亚洲jizzjizz日本少妇| 最好看的2019的中文字幕视频| 亚洲精品久久久久久久久久久久久| 亚洲伊人第一页| 午夜精品久久久久久久99黑人| 在线视频免费一区二区| 亚洲天堂视频在线观看| 国产亚洲aⅴaaaaaa毛片| 国产成人精品免高潮费视频| 国产精品视频一区二区高潮| 欧美日韩美女在线| 欧美国产日韩一区二区在线观看| 欧美激情精品久久久久久久变态| 国产精品视频yy9099| 91精品久久久久久久久中文字幕| 日韩av免费看网站| 久久视频免费在线播放| 亚洲成人黄色在线| 激情av一区二区| 欧美激情一区二区三区在线视频观看| 欧美成人免费播放| 国产精品丝袜久久久久久高清| 日韩视频免费中文字幕| 国产欧美日韩免费| 国产精品视频免费在线观看| 国产999精品| 国产一区二区久久精品| 欧美日韩在线一区| 国产成一区二区| 韩国视频理论视频久久| 欧美在线欧美在线| 欧美裸体男粗大视频在线观看| 亚洲精品理论电影| www欧美日韩| 欧美激情在线狂野欧美精品| 欧美国产日韩在线| 亚洲一区二区在线播放| 中国日韩欧美久久久久久久久| 亚洲一区二区三区在线免费观看| 国产91色在线播放| 成人国产亚洲精品a区天堂华泰| 欧美日韩成人在线观看| 欧美性极品xxxx做受| 亚洲天堂开心观看| 国产高清视频一区三区| 欧美日韩爱爱视频| 成人妇女淫片aaaa视频| 中文字幕亚洲一区二区三区五十路| 国产午夜精品麻豆| 琪琪亚洲精品午夜在线| 国产在线观看不卡| 久久久噜噜噜久久中文字免|