• 多线程编程中的lock的概念
  • 惠娟 发表于 2016/3/4 9:48:00 | 分类标签: 多线程 死锁 lock
  •  在应用程序中使用多个线程的一个好处是每个线程都可以异步执行。然而,线程的异步特性意味着必须协调对资源(如文件句柄、网络连接和内存)的访问。否则,两个或更多的线程可能在同一时间访问相同的资源,而每个线程都不知道其他线程的操作。结果将产生不可预知的数据损坏。这个时候我们就需要lock上场了。

    Lock的作用

    Lock获取给定对象的互斥锁,保证相应的代码块运行时,不会被其他线程中断;直到该对象被释放时其他线程才能访问相应的代码块;

    Lock实现本质

    通过System.Threading.Monitorenterexit方法实现的

    代码实例如下

     1 public void PrintByInnerObj(object greating)
     2        { 
     3            Console.WriteLine(greating+"-- before lock");           
     4            object obj = new object();           
     5            lock(obj)
     6            {
     7                Console.WriteLine(greating + "-- is locking");
     8                Console.WriteLine(greating.ToString());
     9                System.Threading.Thread.Sleep(10000);
    10            }
    11            Console.WriteLine(greating + "--  has unlock");
    12        }

    对应的MSIL代码如下

     

     1 .method public hidebysig instance void  PrintByInnerObj(object greating) cil managed
     2 {
     3   // Code size       116 (0x74)
     4   .maxstack  2
     5   .locals init ([0object obj,
     6            [1bool '<>s__LockTaken0',
     7            [2object CS$2$0000,
     8            [3bool CS$4$0001)
     9   IL_0000:  nop
    10   IL_0001:  ldarg.1
    11   IL_0002:  ldstr      "-- before lock"
    12   IL_0007:  call       string [mscorlib]System.String::Concat(object,
    13                                                               object)
    14   IL_000c:  call       void [mscorlib]System.Console::WriteLine(string)
    15   IL_0011:  nop
    16   IL_0012:  newobj     instance void [mscorlib]System.Object::.ctor()
    17   IL_0017:  stloc.0
    18   IL_0018:  ldc.i4.0
    19   IL_0019:  stloc.1
    20   .try
    21   {
    22     IL_001a:  ldloc.0
    23     IL_001b:  dup
    24     IL_001c:  stloc.2
    25     IL_001d:  ldloca.s   '<>s__LockTaken0'
    26     IL_001f:  call       void [mscorlib]System.Threading.Monitor::Enter(object,
    27                                                                         bool&)
    28     IL_0024:  nop
    29     IL_0025:  nop
    30     IL_0026:  ldarg.1
    31     IL_0027:  ldstr      "-- is locking"
    32     IL_002c:  call       string [mscorlib]System.String::Concat(object,
    33                                                                 object)
    34     IL_0031:  call       void [mscorlib]System.Console::WriteLine(string)
    35     IL_0036:  nop
    36     IL_0037:  ldarg.1
    37     IL_0038:  callvirt   instance string [mscorlib]System.Object::ToString()
    38     IL_003d:  call       void [mscorlib]System.Console::WriteLine(string)
    39     IL_0042:  nop
    40     IL_0043:  ldc.i4     0x2710
    41     IL_0048:  call       void [mscorlib]System.Threading.Thread::Sleep(int32)
    42     IL_004d:  nop
    43     IL_004e:  nop
    44     IL_004f:  leave.s    IL_0061
    45   }  // end .try
    46   finally
    47   {
    48     IL_0051:  ldloc.1
    49     IL_0052:  ldc.i4.0
    50     IL_0053:  ceq
    51     IL_0055:  stloc.3
    52     IL_0056:  ldloc.3
    53     IL_0057:  brtrue.s   IL_0060
    54     IL_0059:  ldloc.2
    55     IL_005a:  call       void [mscorlib]System.Threading.Monitor::Exit(object)
    56     IL_005f:  nop
    57     IL_0060:  endfinally
    58   }  // end handler
    59   IL_0061:  nop
    60   IL_0062:  ldarg.1
    61   IL_0063:  ldstr      "--  has unlock"
    62   IL_0068:  call       string [mscorlib]System.String::Concat(object,
    63                                                               object)
    64   IL_006d:  call       void [mscorlib]System.Console::WriteLine(string)
    65   IL_0072:  nop
    66   IL_0073:  ret
    67 // end of method MyLockTest::PrintByInnerObj

     

    Lock的锁定范围

    Lock的参数必须为引用类型的对象,该对象代表了锁定的范围,对象不同锁定的范围也不同。 锁定参数为待锁定代码块内声明的对象,锁定范围为该代码块

     1 public void PrintByInnerObj(objectgreating)
     2 
     3 
     4 
     5 Console.WriteLine(greating+"-- before lock"); 
     6 
     7 object obj=newobject(); 
     8 
     9 lock(obj)
    10 
    11 {
    12 
    13 Console.WriteLine(greating+"-- is locking");
    14 
    15 Console.WriteLine(greating.ToString());
    16 
    17 System.Threading.Thread.Sleep(10000);
    18 
    19 }
    20 
    21 Console.WriteLine(greating+"-- has unlock");
    22 
    23 }

    锁定参数为待锁定代码块所在类的私有字段,锁定范围为该类具体的一个实例

     1 public void PrintByInstanceObj(objectgreating)
     2 
     3 {
     4 
     5 Console.WriteLine(greating+"-- before lock"); 
     6 
     7 lock (instanceObj)
     8 
     9 {
    10 
    11 Console.WriteLine(greating+"-- is locking");
    12 
    13 Console.WriteLine(greating.ToString());
    14 
    15 System.Threading.Thread.Sleep(10000);
    16 
    17 }
    18 
    19 Console.WriteLine(greating+"-- has unlock");
    20 
    21 }

    锁定参数为待锁定代码块所在类的私有静态字段,锁定范围为该类所有的实例


     1 public void PrintLockByStaticObj(objectgreating)
     2 
     3 {
     4 
     5 Console.WriteLine(greating+"-- before lock"); 
     6 
     7 lock (staticObj)
     8 
     9 {
    10 
    11 Console.WriteLine(greating+"-- is locking");
    12 
    13 Console.WriteLine(greating.ToString());
    14 
    15 Thread.Sleep(10000);
    16 
    17 }
    18 
    19 Console.WriteLine(greating+"-- has unlock");
    20 
    21 }

    锁定参数为某一字符串,锁定范围为与该字符串值相等的所有字符串

     1 public void PrintLockByStringObj(objectgreating)
     2 
     3 {
     4 
     5 Console.WriteLine(greating+"-- before lock"); 
     6 
     7 lock (stringObj)
     8 
     9 {
    10 
    11 Console.WriteLine(greating+"-- is locking");
    12 
    13 Console.WriteLine(greating.ToString());
    14 
    15 System.Threading.Thread.Sleep(10000);
    16 
    17 }
    18 
    19 Console.WriteLine(greating+"--has unlock");
    20 
    21 }
    22 
    23 
    24 public void PrintLockByString(objectgreating)
    25 
    26 {
    27 
    28 Console.WriteLine(greating+"-- before lock"); 
    29 
    30 lock ("lock")
    31 
    32 {
    33 
    34 Console.WriteLine(greating+"-- is locking");
    35 
    36 Console.WriteLine(greating.ToString());
    37 
    38 System.Threading.Thread.Sleep(10000);
    39 
    40 }
    41 
    42 Console.WriteLine(greating+"--has unlock");
    43 
    44 

    锁定参数为this,锁定范围为所有能访问到this的地方

     1 public void PrintLockByThis(objectgreating)
     2 
     3 {
     4 
     5 Console.WriteLine(greating+"-- before lock"); 
     6 
     7 lock (this)
     8 
     9 {
    10 
    11 Console.WriteLine(greating+"-- is locking");
    12 
    13 Console.WriteLine(greating.ToString());
    14 
    15 System.Threading.Thread.Sleep(10000);
    16 
    17 }
    18 
    19 Console.WriteLine(greating+"--has unlock");
    20 
    21 }

    锁定参数为某个类的System.Type的实例,锁定范围为所有的地方锁定public的实例字段,锁定范围同锁定this


     1 public void PrintLockByPublicInstanceObj(objectgreating)
     2 
     3 {
     4 
     5 Console.WriteLine(greating+"-- before lock");
     6 
     7 lock (publicInstanceObj)
     8 
     9 {
    10 
    11 Console.WriteLine(greating+"-- is locking");
    12 
    13 Console.WriteLine(greating.ToString());
    14 
    15 System.Threading.Thread.Sleep(10000);
    16 
    17 }
    18 
    19 Console.WriteLine(greating+"--has unlock");
    20 
    21 }

    锁定参数为public的静态字段,锁定范围与锁定system.type相同

     1 public void PrintLockByPublicStaticObj(objectgreating)
     2 
     3 {
     4 
     5 Console.WriteLine(greating+"-- before lock");
     6 
     7 lock (publicStaticObj)
     8 
     9 {
    10 
    11 Console.WriteLine(greating+"-- is locking");
    12 
    13 Console.WriteLine(greating.ToString());
    14 
    15 System.Threading.Thread.Sleep(10000);
    16 
    17 }
    18 
    19 Console.WriteLine(greating+"--has unlock");
    20 
    21 }

    整个类的代码如下

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.Threading;
      6 
      7 namespace LockCVolatileCA
      8 {
      9    public class MyLockTest
     10     {
     11        private static object staticObj = new object();
     12        private object instanceObj = new object();
     13        public static object publicStaticObj = new object();
     14        public object publicInstanceObj = new object();
     15        private string stringObj = "lock";
     16        private static Int32 i = new int()  ;
     17 
     18        public void PrintByInnerObj(object greating)
     19        { 
     20            Console.WriteLine(greating+"-- before lock");          
     21            object obj = new object();           
     22            lock(obj)
     23            {
     24                Console.WriteLine(greating + "-- is locking");
     25                Console.WriteLine(greating.ToString());
     26                System.Threading.Thread.Sleep(10000);
     27            }
     28            Console.WriteLine(greating + "--  has unlock");
     29        }
     30 
     31        public void PrintByInstanceObj(object greating)
     32        {
     33            Console.WriteLine(greating + "-- before lock");                    
     34            lock (instanceObj)
     35            {
     36                Console.WriteLine(greating + "-- is locking");
     37                Console.WriteLine(greating.ToString());
     38                System.Threading.Thread.Sleep(10000);
     39            }
     40            Console.WriteLine(greating + "--  has unlock");
     41        }
     42 
     43        public void PrintLockByStaticObj(object greating)
     44        {
     45            Console.WriteLine(greating + "-- before lock");           
     46            lock (staticObj)
     47            {
     48                Console.WriteLine(greating + "-- is locking");
     49                Console.WriteLine(greating.ToString());
     50                Thread.Sleep(10000);
     51            }
     52            Console.WriteLine(greating + "-- has unlock");
     53        }
     54 
     55        public void PrintLockByClass(object greating)
     56        {
     57            Console.WriteLine(greating + "-- before lock");         
     58            lock (typeof(MyLockTest))
     59            {
     60                Console.WriteLine(greating + "-- is locking");
     61                Console.WriteLine(greating.ToString());
     62                Thread.Sleep(1000);
     63            }
     64            Console.WriteLine(greating + "-- has unlock");
     65        }
     66 
     67        public void PrintLockByThis(object greating)
     68        {
     69            Console.WriteLine(greating + "-- before lock");        
     70            lock (this)
     71            {
     72                Console.WriteLine(greating + "-- is locking");
     73                Console.WriteLine(greating.ToString());
     74                System.Threading.Thread.Sleep(10000);
     75            }
     76            Console.WriteLine(greating + "--has unlock");
     77        }
     78 
     79        public void PrintLockByStringObj(object greating)
     80        {
     81            Console.WriteLine(greating + "-- before lock");       
     82            lock (stringObj)
     83            {
     84                Console.WriteLine(greating + "-- is locking");
     85                Console.WriteLine(greating.ToString());
     86                System.Threading.Thread.Sleep(10000);
     87            }
     88            Console.WriteLine(greating + "--has unlock");
     89        }
     90 
     91        public void PrintLockByString(object greating)
     92        {
     93            Console.WriteLine(greating + "-- before lock");         
     94            lock ("lock")
     95            {
     96                Console.WriteLine(greating + "-- is locking");
     97                Console.WriteLine(greating.ToString());
     98                System.Threading.Thread.Sleep(10000);
     99            }
    100            Console.WriteLine(greating + "--has unlock");
    101        }
    102 
    103        public void PrintLockByPublicStaticObj(object greating)
    104        {
    105            Console.WriteLine(greating + "-- before lock");           
    106            lock (publicStaticObj)
    107            {
    108                Console.WriteLine(greating + "-- is locking");
    109                Console.WriteLine(greating.ToString());
    110                System.Threading.Thread.Sleep(10000);
    111            }
    112            Console.WriteLine(greating + "--has unlock");
    113        }
    114 
    115        public void PrintLockByPublicInstanceObj(object greating)
    116        {
    117            Console.WriteLine(greating + "-- before lock");
    118            lock (publicInstanceObj)
    119            {
    120                Console.WriteLine(greating + "-- is locking");
    121                Console.WriteLine(greating.ToString());
    122                System.Threading.Thread.Sleep(10000);
    123            }
    124            Console.WriteLine(greating + "--has unlock");
    125        }       
    126     }
    127 }

     

  • 请您注意

    ·自觉遵守:爱国、守法、自律、真实、文明的原则

    ·尊重网上道德,遵守《全国人大常委会关于维护互联网安全的决定》及中华人民共和国其他各项有关法律法规

    ·严禁发表危害国家安全,破坏民族团结、国家宗教政策和社会稳定,含侮辱、诽谤、教唆、淫秽等内容的作品

    ·承担一切因您的行为而直接或间接导致的民事或刑事法律责任

    ·您在编程中国社区新闻评论发表的作品,本网站有权在网站内保留、转载、引用或者删除

    ·参与本评论即表明您已经阅读并接受上述条款

  • 感谢本文作者
  • 作者头像
  • 昵称:惠娟
  • 加入时间:2013/5/11 0:00:00
  • TA的签名
  • 这家伙很懒,虾米都没写
  • +进入TA的空间
  • 以下内容也很赞哦
分享按钮