第十一節:深究用戶模式鎖的使用場景(異變結構、互鎖、旋轉鎖)

一. 鎖機制的背景介紹html

  本章節,將結合多線程來介紹鎖機制, 那麼問題來了,什麼是鎖呢? 爲何須要鎖? 爲何要結合多線程來介紹鎖呢?鎖的使用場景又是什麼呢? DotNet中又有哪些鎖呢?多線程

  在接下來的幾個章節中,將陸續解答這些問題。併發

PS:spa

  多個線程對一個共享資源進行使用的時候,會出問題, 好比實際的業務場景,入庫和出庫操做同時進行,庫存量就會存在併發問題。因此鎖就是用來解決多線程資源競用的問題。線程

  Net領域中,鎖機制很是多,好比:時間鎖、信號量、互斥鎖、讀寫鎖、互鎖、異變結構,主要咱們能夠把他們劃分爲三大類:3d

    ①.用戶模式鎖:就是經過一些cpu指令或者一個死循環,來達到達到線程的等待和休眠。
    ②.內核模式鎖:就是調用win32底層的代碼,來實現thread的各類操做。
    ③.混合鎖:用戶模式+內核模式code

  其中用戶模式鎖又分爲這麼幾類:異變結構、互鎖和旋轉鎖。htm

二. 異變結構blog

背景:一個線程讀,一個線程寫,在release模式下會出現bug,致使主線程沒法執行,緣由在前面章節已經介紹過了。資源

  方式一:利用MemoryBarrier方法進行處理 。(前面章節已介紹

  方式二:利用VolatileRead/Write方法進行處理。 (前面章節已介紹)

  方式三:volatile關鍵字進行處理,個人read和write都是從memrory中讀取,讀取的都是最新的。(下面的案例使用volatile關鍵字後,主線程能夠執行)

 代碼實踐:

 1             public static volatile bool isStop = false;
2 //使用Volatile關鍵字處理 3 var t = new Thread(() => 4 { 5 var isSuccess = false; 6 while (!isStop) 7 { 8 isSuccess = !isSuccess; 9 } 10 }); 11 t.Start(); 12 Thread.Sleep(1000); 13 isStop = true; 14 t.Join(); 15 Console.WriteLine("主線程執行結束!"); 16 Console.ReadLine();

代碼結論:使用volatile關鍵字進行修飾,解決共享資源的競用問題。

三. 互鎖

  互鎖結構(Interlocked類),經常使用的方法有:

    * Increment:自增操做

    * Decrement:自減操做

    * Add: 增長指定的值

    * Exchange: 賦值

    * CompareExchange: 比較賦值

 代碼實踐:

 1             {
 2                 //1. 自增
 3                 {
 4                     int a = 1;
 5                     Interlocked.Increment(ref a);
 6                     Console.WriteLine("自增後的數據爲:{0}", a);
 7                 }
 8                 //2. 自減
 9                 {
10                     int b = 2;
11                     Interlocked.Decrement(ref b);
12                     Console.WriteLine("自減後的數據爲:{0}", b);
13                 }
14                 //3. 增長操做
15                 {
16                     int c = 3;
17                     Interlocked.Add(ref c, 4);
18                     Console.WriteLine("增長後的數據爲:{0}", c);
19 
20                 }
21                 //4. 賦值操做
22                 {
23                     int d = 4;
24                     Interlocked.Exchange(ref d, 55);
25                     Console.WriteLine("賦值後的數據爲:{0}", d);
26 
27                 }
28                 //5. 比較賦值
29                 {
30                     //Interlocked.CompareExchange(ref num1, sum, num2);  // num1==num2 ; num1=sum;
31                     int ee = 5;
32                     Interlocked.CompareExchange(ref ee, 15, 5);
33                     Console.WriteLine("比較賦值後的數據爲:{0}", ee);
34 
35                     Interlocked.CompareExchange(ref ee, 100, 15);
36                     Console.WriteLine("比較賦值後的數據爲:{0}", ee);
37 
38                 }
39 
40             }

代碼結果:

 

四. 旋轉鎖

  旋轉鎖(SpinLock), 特殊的業務邏輯讓thread在用戶模式下進行自選,欺騙cpu當前thread正在運行中。

   SpinLock類有兩個核心方法,分別是:Enter和Exit方法。

 代碼實踐:

 1             {
 2                 //下面代碼的結果:num從0-249,且是有序的。
 3                 //若是把旋轉鎖去掉,num將沒有任何順序
 4                 for (int i = 0; i < 5; i++)
 5                 {
 6                     Task.Factory.StartNew(() =>
 7                     {
 8                         for (int j = 0; j < 50; j++)
 9                         {
10                             try
11                             {
12                                 var b = false;
13                                 sl.Enter(ref b);
14                                 Console.WriteLine(num++);
15                             }
16                             catch (Exception ex)
17                             {
18                                 Console.WriteLine(ex.Message);
19                             }
20                             finally
21                             {
22                                 sl.Exit();
23                             }
24                         }
25                     });
26                 }
27             }

代碼結果:下面代碼的結果:num從0-249,且是有序的;若是將旋轉鎖的代碼去掉,num的輸出將沒有任何順序可言。

 

 

 

相關文章
相關標籤/搜索