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

首頁 > 學院 > 開發設計 > 正文

多線程中的鎖系統(一)-基礎用法

2019-11-17 01:56:15
字體:
來源:轉載
供稿:網友

多線程中的鎖系統(一)-基礎用法

2014-12-21 22:55 by 蘑菇先生, ... 閱讀, ... 評論, 收藏, 編輯

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

閱讀目錄:

  1. lock、Monitor
  2. 作用域范圍
  3. 字符串鎖
  4. Monitor的用法
  5. Mutex
  6. Semaphore
  7. 總結

lock、Monitor

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 是可以鎖值類型的。鎖時會裝箱成新對象,所以無法做到線程同步。

作用域范圍

一: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 heapMSCorLib.dll中的int實例會一直保留著,直到進程結束。單個程序域卸載也不受影響。作用域很大有沒有?。?!

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

字符串的鎖

我們都知道鎖的目的,是為了多線程下值被破壞。也知道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。

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);可以釋放多個,但不能超過最大值。如果最后釋放的總量超過本身總量,也會報錯。 不建議使用
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品国产91久久久久久| 国产精品久久久久久亚洲影视| 欧美在线免费看| 国产日韩精品在线观看| 上原亚衣av一区二区三区| 日韩的一区二区| 亚洲乱亚洲乱妇无码| 91免费在线视频网站| 色偷偷偷亚洲综合网另类| 亚洲欧洲中文天堂| 国内外成人免费激情在线视频网站| 亚洲免费成人av电影| 中文字幕欧美专区| 亚洲91av视频| 精品免费在线观看| 亚洲人成在线播放| 中文字幕久热精品视频在线| 欧美不卡视频一区发布| 亚洲国产精品久久久久久| 欧美性猛交视频| 国产精品久久久久久搜索| 欧美日韩电影在线观看| 91视频国产精品| 91在线视频精品| 日韩精品一二三四区| 一区二区三区视频免费在线观看| 国产成人久久精品| 成人h视频在线观看播放| 少妇高潮 亚洲精品| 国产精品69久久久久| 国产精品99久久久久久白浆小说| 国产精品吊钟奶在线| 国产精品自拍视频| 亚洲自拍中文字幕| 午夜精品在线视频| 97在线观看免费高清| 久久高清视频免费| 久久精品国亚洲| 精品高清一区二区三区| 国产亚洲福利一区| 国产精品久久久久久网站| 欧美激情乱人伦| 91av免费观看91av精品在线| 色综合久久天天综线观看| 88国产精品欧美一区二区三区| 97国产精品视频人人做人人爱| 91色琪琪电影亚洲精品久久| 国内精品久久久久久影视8| 国产丝袜一区二区| 亚洲精品成人久久久| 亚洲国产高清高潮精品美女| 亚洲爱爱爱爱爱| 亚洲欧洲一区二区三区久久| 亚洲性视频网站| 日韩在线中文字| 亚洲精品久久7777777| 精品美女永久免费视频| 成人免费观看a| 欧美电影免费观看电视剧大全| 在线观看欧美www| 久久五月天综合| 亚洲成av人影院在线观看| 91精品国产综合久久久久久久久| 亚洲精品日韩欧美| 欧美日韩裸体免费视频| 爽爽爽爽爽爽爽成人免费观看| 亚洲老头同性xxxxx| 国产精品久久久久7777婷婷| 久久久免费高清电视剧观看| 欧美日韩另类视频| 欧美成人h版在线观看| 中日韩午夜理伦电影免费| 日本不卡免费高清视频| 欧美国产第二页| 国产精品一区二区在线| 欧美精品久久久久a| 欧美精品999| 日韩在线观看精品| 中国人与牲禽动交精品| 日韩免费观看高清| 粉嫩av一区二区三区免费野| 亚洲一区二区三区视频播放| 亚洲精品一区二三区不卡| 欧美日韩免费观看中文| 精品久久久久久亚洲精品| 国产精品久久久久久久app| 91地址最新发布| 国产精品久久久av久久久| 亚洲一区国产精品| 久久777国产线看观看精品| 国产精品视频永久免费播放| 亚洲成人精品av| 日韩精品中文字幕在线观看| 欧美夜福利tv在线| 亚洲黄页视频免费观看| 亚洲视频电影图片偷拍一区| 美乳少妇欧美精品| 91精品久久久久久久久青青| 亚洲精品www久久久久久广东| 国产精品色视频| 亚洲色图15p| 欧美极品欧美精品欧美视频| 成人黄色生活片| 国产精选久久久久久| 国产午夜精品全部视频在线播放| 国产精品久久久久99| 免费不卡在线观看av| 精品亚洲夜色av98在线观看| 国产日本欧美一区| 日韩av在线一区| 亚洲深夜福利视频| 97超级碰碰人国产在线观看| 久久久久久97| 国语自产精品视频在线看抢先版图片| 亚洲欧美日韩另类| 亚洲综合中文字幕在线观看| 2021国产精品视频| 亚洲视频在线播放| 久久在线观看视频| 亚洲精品动漫久久久久| 1769国内精品视频在线播放| 欧美极品少妇xxxxⅹ裸体艺术| 亚洲美腿欧美激情另类| 清纯唯美亚洲综合| 亚洲第一偷拍网| 亚洲欧美成人网| 7777kkkk成人观看| 亚洲免费成人av电影| 日本不卡免费高清视频| 久久亚洲影音av资源网| 亚洲精品黄网在线观看| 57pao成人永久免费视频| 91久久精品美女| 日韩av一区在线| 国产精品成人播放| 国产成人一区二区三区| 日本精品在线视频| 国内精品久久久久久久久| 欧美怡春院一区二区三区| 欧美大片在线免费观看| 日韩电影视频免费| 丝袜美腿精品国产二区| 91精品国产色综合| 久久久久久久色| 亚洲影院色在线观看免费| 欧美中文在线观看国产| 不卡在线观看电视剧完整版| 日韩欧美一区视频| 精品一区二区电影| 国产大片精品免费永久看nba| 国产一区二区三区四区福利| 日韩国产精品一区| 少妇激情综合网| 亚洲男人天堂网站| 欧美高清不卡在线| 日本高清不卡在线| 亚洲色图激情小说| 久久久亚洲天堂| 欧美大荫蒂xxx| 96sao精品视频在线观看| 国产成+人+综合+亚洲欧洲| 久久人人爽人人爽人人片av高清| 黄色成人在线播放| 亚洲在线免费观看|