異步多線程(六)lock鎖


非線程安全

   引發線程安全的原因是,多個線程可以同時操作全局變量/共享變量/靜態變量/磁盤文件/數據庫的值就可能存在線程安全問題,因為多個線程操作,出現了覆蓋。List集合也是非線程安全的。

 

線程安全

多線程同時運行,如果每次運行的結果和單線程運行的結果一致,那么就是線程安全的。

 

Lock

概念

   解決多線程沖突問題,Lock是語法糖,Monitor.Enter,占據一個引用,別的線程就只能等着。鎖的本質就是把多線程在某些特定場合下變成單線程,來完成某些特定操作。

在日常工作中,有些是特定需要鎖的,更多的時候我們可以把數據拆分,避免多線程操作同一個數據,這樣既安全又高效。例如有10000個任務,那可以進行拆分,某個線程執行1-100給任務。

 

Lock鎖不允許的類型

  Stringstring在內存分配上是重用的,會沖突。這么話應該這么理解,比如你定義一個變量name=張三”,再定義一個變量temeName=張三,那么在C#內存分配時會指向同一個引用。

  Null:可以運行,不能編譯通過。

 

詳解Lock

Lock鎖的兩鍾方式:

Lock(this)不推薦的鎖如果只是當前內部實例使用,則不會沖突。外面如果也要用實例,就沖突了。 

 

        public void DoTest() {
            //遞歸調用 lock(this)不會死鎖,原因:這里是同一個線程,這個引用就是被這個線程鎖占據
            //鎖的本質是讓這個引用不會被其他線程所占據
        lock (this)
        {
                Thread.Sleep(500);
                iDotestNum++;
                if (DateTime.Now.Day < 13&&iDotestNum<10)
                {
                    
                    Console.WriteLine($"這是第{DateTime.Now.Day}天,第{iDotestNum}次");
                    this.DoTest();
                }
                else {
                    Console.WriteLine("結束啦");
                }
                }
        }

        private int iDotestNum = 0;

 

 

外部也要使用實例:

            Test test = new Test();
            Task.Delay(1000).ContinueWith(t =>
            {
                lock (test)//此處是鎖住test實例
                {
                    Console.WriteLine("*********Start**********");
                    Thread.Sleep(5000);
                    Console.WriteLine("*********End**********");
                }
            });
            //會沖突,因為DoTest方法里的lock(this)就是鎖住當前的實例即:test
            test.DoTest();

        public class Test{ 

        public void DoTest() {
            //遞歸調用 lock(this)不會死鎖,原因:這里是同一個線程,這個引用就是被這個線程鎖占據
            //鎖的本質是讓這個引用不會被其他線程所占據
        lock (this)
        {
                Thread.Sleep(500);
                iDotestNum++;
                if (DateTime.Now.Day < 13&&iDotestNum<10)
                {
                    
                    Console.WriteLine($"這是第{DateTime.Now.Day}天,第{iDotestNum}次");
                    this.DoTest();
                }
                else {
                    Console.WriteLine("結束啦");
                }
                }
        }

        private int iDotestNum = 0;
    }

 

 

 

 

 

標准鎖,微軟推薦的標准鎖

 

private static readonly object Form_Lock = new object();

lock(Form_Lock);

            #region 標准鎖

            for (int i = 0; i < 1000; i++)
            {      
                   Task.Run(() =>
                   {
                       lock (Form_Lock)// 任意時刻只有一個線程能進入方法塊兒
                       {
                           intAsyncNum++;
                       }
                   });
            }
            Console.WriteLine($"intAsyncNum={intAsyncNum}");

            #endregion

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM