亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C#多線(xiàn)程系列之多線(xiàn)程鎖lock和Monitor

 更新時(shí)間:2022年02月13日 11:43:34   作者:癡者工良  
這篇文章介紹了C#多線(xiàn)程鎖lock和Monitor的用法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

1,Lock

lock 用于讀一個(gè)引用類(lèi)型進(jìn)行加鎖,同一時(shí)刻內(nèi)只有一個(gè)線(xiàn)程能夠訪(fǎng)問(wèn)此對(duì)象。lock 是語(yǔ)法糖,是通過(guò) Monitor 來(lái)實(shí)現(xiàn)的。

Lock 鎖定的對(duì)象,應(yīng)該是靜態(tài)的引用類(lèi)型(字符串除外)。

實(shí)際上字符串也可以作為鎖的對(duì)象使用,只是由于字符串對(duì)象的特殊性,可能會(huì)造成不同位置的不同線(xiàn)程沖突。
如果你能保證字符串的唯一性,例如 Guid 生成的字符串,也是可以作為鎖的對(duì)象使用的(但不建議)。 
鎖的對(duì)象也不一定要靜態(tài)才行,也可以通過(guò)類(lèi)實(shí)例的成員變量,作為鎖對(duì)象。

lock 原型

lock 是 Monitor 的語(yǔ)法糖,生成的代碼對(duì)比:

lock (x)
{
    // Your code...
}
object __lockObj = x;
bool __lockWasTaken = false;
try
{
    System.Threading.Monitor.Enter(__lockObj, ref __lockWasTaken);
    // Your code...
}
finally
{
    if (__lockWasTaken) System.Threading.Monitor.Exit(__lockObj);
}

這里先不理會(huì) Monitor,后面再說(shuō)。

lock 編寫(xiě)實(shí)例

首先,如果像下面這樣寫(xiě)的話(huà),拉出去打 si 吧。

        public void MyLock()
        {
            object o = new object();
            lock (o)
            {
            // 
            }
        }

下面編寫(xiě)一個(gè)簡(jiǎn)單的鎖,示例如下:

    class Program
    {
        private static object obj = new object();
        private static int sum = 0;
        static void Main(string[] args)
        {

            Thread thread1 = new Thread(Sum1);
            thread1.Start();
            Thread thread2 = new Thread(Sum2);
            thread2.Start();
            while (true)
            {
                Console.WriteLine($"{DateTime.Now.ToString()}:" + sum);
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
        }

        public static void Sum1()
        {
            sum = 0;
            lock (obj)
            {
                for (int i = 0; i < 10; i++)
                {
                    sum += i;
                    Console.WriteLine("Sum1");
                    Thread.Sleep(TimeSpan.FromSeconds(2));
                }
            }
        }

        public static void Sum2()
        {
            sum = 0;
            lock (obj)
            {
                for (int i = 0; i < 10; i++)
                {
                    sum += 1;
                    Console.WriteLine("Sum2");
                    Thread.Sleep(TimeSpan.FromSeconds(2));
                }
            }
        }
    }

類(lèi)將自己設(shè)置為鎖, 這可以防止惡意代碼對(duì)公共對(duì)象采用做鎖。

例如:

  public void Access()
    {
        lock(this) {}
     }

鎖可以阻止其它線(xiàn)程執(zhí)行鎖塊(lock(o){})中的代碼,當(dāng)鎖定時(shí),其它線(xiàn)程必須等待鎖中的線(xiàn)程執(zhí)行完成并釋放鎖。但是這可能會(huì)給程序帶來(lái)性能影響。
鎖不太適合I/O場(chǎng)景,例如文件I/O,繁雜的計(jì)算或者操作比較持久的過(guò)程,會(huì)給程序帶來(lái)很大的性能損失。

10 種優(yōu)化鎖的性能方法: http://www.thinkingparallel.com/2007/07/31/10-ways-to-reduce-lock-contention-in-threaded-programs/

2,Monitor

此對(duì)象提供同步訪(fǎng)問(wèn)對(duì)象的機(jī)制;Monotor 是一個(gè)靜態(tài)類(lèi)型,其方法比較少,常用方法如下:

操作說(shuō)明
Enter, TryEnter獲取對(duì)象的鎖。 此操作還標(biāo)記關(guān)鍵節(jié)的開(kāi)頭。 其他任何線(xiàn)程都不能輸入臨界區(qū),除非它使用不同的鎖定對(duì)象執(zhí)行臨界區(qū)中的說(shuō)明。
Wait釋放對(duì)象的鎖,以允許其他線(xiàn)程鎖定并訪(fǎng)問(wèn)對(duì)象。 調(diào)用線(xiàn)程會(huì)等待另一個(gè)線(xiàn)程訪(fǎng)問(wèn)對(duì)象。 使用脈沖信號(hào)通知等待線(xiàn)程關(guān)于對(duì)象狀態(tài)的更改。
Pulse 、PulseAll將信號(hào)發(fā)送到一個(gè)或多個(gè)等待線(xiàn)程。 信號(hào)通知等待線(xiàn)程:鎖定對(duì)象的狀態(tài)已更改,鎖的所有者已準(zhǔn)備好釋放該鎖。 正在等待的線(xiàn)程置于對(duì)象的就緒隊(duì)列中,因此它可能最終接收對(duì)象的鎖。 線(xiàn)程鎖定后,它可以檢查對(duì)象的新?tīng)顟B(tài),以查看是否已達(dá)到所需的狀態(tài)。
Exit釋放對(duì)象的鎖。 此操作還標(biāo)記受鎖定對(duì)象保護(hù)的臨界區(qū)的結(jié)尾。

怎么用呢

下面是一個(gè)很簡(jiǎn)單的示例:

        private static object obj = new object();
        private static bool acquiredLock = false;
		
		public static void Test()
        {
            try
            {
                Monitor.Enter(obj, ref acquiredLock);
            }
            catch { }
            finally
            {
                if (acquiredLock)
                    Monitor.Exit(obj);
            }
        }

Monitor.Enter 鎖定 obj 這個(gè)對(duì)象,并且設(shè)置 acquiredLock 為 true,告訴別人 obj 已經(jīng)被鎖定。

最后結(jié)束時(shí),判斷 acquiredLock ,釋放鎖,并設(shè)置 acquiredLock 為 false。

解釋一下

臨界區(qū):指被某些符號(hào)包圍的范圍。例如 {} 內(nèi)。

Monitor 對(duì)象的 Enter 和 Exit 方法來(lái)標(biāo)記臨界區(qū)的開(kāi)頭和結(jié)尾。

Enter() 方法獲取鎖后,能夠保證只有單個(gè)線(xiàn)程能夠使用臨界區(qū)中的代碼。使用 Monitor 類(lèi),最好搭配 try{...}catch{...}finally{...} 來(lái)使用,因?yàn)槿绻@取到鎖但是沒(méi)有釋放鎖的話(huà),會(huì)導(dǎo)致其它線(xiàn)程無(wú)限阻塞,即發(fā)生死鎖。

一般來(lái)說(shuō),lock 關(guān)鍵字夠用了。

示例

下面示范了多個(gè)線(xiàn)程如何使用 Monitor 來(lái)實(shí)現(xiàn)鎖:

       private static object obj = new object();
        private static bool acquiredLock = false;
        static void Main(string[] args)
        {
            new Thread(Test1).Start();
            Thread.Sleep(1000);
            new Thread(Test2).Start();
        }

        public static void Test1()
        {
            try
            {
                Monitor.Enter(obj, ref acquiredLock);
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("Test1正在鎖定資源");
                    Thread.Sleep(1000);
                }

            }
            catch { }
            finally
            {
                if (acquiredLock)
                    Monitor.Exit(obj);
                Console.WriteLine("Test1已經(jīng)釋放資源");
            }
        }
        public static void Test2()
        {
            bool isGetLock = false;
            Monitor.Enter(obj);
            try
            {
                Monitor.Enter(obj, ref acquiredLock);
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("Test2正在鎖定資源");
                    Thread.Sleep(1000);
                }

            }
            catch { }
            finally
            {
                if (acquiredLock)
                    Monitor.Exit(obj);
                Console.WriteLine("Test2已經(jīng)釋放資源");
            }
        }

設(shè)置獲取鎖的時(shí)效

如果對(duì)象已經(jīng)被鎖定,另一個(gè)線(xiàn)程使用 Monitor.Enter 對(duì)象,就會(huì)一直等待另一個(gè)線(xiàn)程解除鎖定。

但是,如果一個(gè)線(xiàn)程發(fā)生問(wèn)題或者出現(xiàn)死鎖的情況,鎖一直被鎖定呢?或者線(xiàn)程具有時(shí)效性,超過(guò)一段時(shí)間不執(zhí)行,已經(jīng)沒(méi)有了意義呢?

我們可以通過(guò) Monitor.TryEnter() 來(lái)設(shè)置等待時(shí)間,超過(guò)一段時(shí)間后,如果鎖還沒(méi)有釋放,就會(huì)返回 false。

改造上面的示例如下:

        private static object obj = new object();
        private static bool acquiredLock = false;
        static void Main(string[] args)
        {
            new Thread(Test1).Start();
            Thread.Sleep(1000);
            new Thread(Test2).Start();
        }

        public static void Test1()
        {
            try
            {
                Monitor.Enter(obj, ref acquiredLock);
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("Test1正在鎖定資源");
                    Thread.Sleep(1000);
                }
            }
            catch { }
            finally
            {
                if (acquiredLock)
                    Monitor.Exit(obj);
                Console.WriteLine("Test1已經(jīng)釋放資源");
            }
        }
        public static void Test2()
        {
            bool isGetLock = false;
            isGetLock = Monitor.TryEnter(obj, 500);
            if (isGetLock == false)
            {
                Console.WriteLine("鎖還沒(méi)有釋放,我不干活了");
                return;
            }
            try
            {
                Monitor.Enter(obj, ref acquiredLock);
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("Test2正在鎖定資源");
                    Thread.Sleep(1000);
                }
            }
            catch { }
            finally
            {
                if (acquiredLock)
                    Monitor.Exit(obj);
                Console.WriteLine("Test2已經(jīng)釋放資源");
            }
        }

到此這篇關(guān)于C#多線(xiàn)程系列之多線(xiàn)程鎖lock和Monitor的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

您可能感興趣的文章:

相關(guān)文章

最新評(píng)論