zoukankan      html  css  js  c++  java
  • 探究c# lock

    今天早上阅读前辈的代码,看到了这么一段代码,如下所示:

    1  lock("Execute")
    2  {
    3       string sqlStr = sbSQLScript.ToString();
    4  }

          看到第一句,我就怀疑了,c#当中的lock可以这么用吗?这是个什么用法,我第一次看到。我百度了下相关的技术资料。lock 一个引用类型,这没啥问题。问题是这个对象是个字符串。字符串在公共运行时clr中暂留,这意味着整个程序中任何给定字符串都只有一个实例,就是这同一个对象表示了所有运行的应用程序域的所有线程中的该文本。因此,只要在应用程序进程中的任何位置处具有相同内容的字符串上放置了锁,就将锁定应用程序中该字符串的所有实例。 

          这一句话,来源于网络上别人的文章,需要验证,看是不是相同的字符串表示同一个对象?

     static void Main(string[] args)
     {
        string a = "wbq";
        string b = "wbq";
        if (a == b && a.Equals(b) && object.ReferenceEquals(a,b))
        {
           Console.WriteLine("i am wbq,i am testing lock");
        }     
    }

    运行结果:

    那是不是字符串内容相同了,就一定是同一个对象呢?

     1     static void Main(string[] args)
     2     {
     3        string a = "wbq";
     4        string b = "w";
     5        b += "bq";
     6 
     7        if (a == b)
     8         {
     9           Console.WriteLine("我们的值相同");
    10 
    11           if (object.ReferenceEquals(a, b))
    12           {
    13 
    14               Console.WriteLine("i am wbq,i am testing lock");
    15            }
    16            else
    17            {
    18               Console.WriteLine("但是我们是两个不同的对象");
    19             }
    20          }
    21     }

     运行结果:

    看到这个结果,是不是一开始很吃惊呢?是的,刚开始的时候,是很吃惊。后来想到,不是前辈教导我们:如果拼接大量的字符串会影响性能,改用StringBuilder吗?刚才的程序演示,果然揭示了这一真理,拼接字符串会产生新的对象,所以如果大量拼接,则会产生大量对象,对象多了,事情就多了。垃圾回收器GC可就忙了,它太忙,势必影响我们程序的性能。另外一方面,内存资源消耗的多了。有人说了,现在的电脑硬件很好什么的,这个不用操心,我就想说,内存还是比较稀缺的资源。水涨船高嘛,内存大了,如今的程序胃口也大开,占用的内存也多了。

         好了,言归正传,我们今天研究的主题是lock,不是string。

         据说lock是个语法糖,它的真面目是 monitor.enter 结构,这个要怎么看才能知道呢?下面是代码:

       

     1 class MainApp
     2 {
     3         class Program
     4         {
     5             private static readonly object lock4 = new object();
     6             static void Main(string[] args)
     7             {
     8 
     9                 lock (lock4)
    10                 {
    11                     Console.WriteLine("i am wbq,i am testing lock");
    12                 }
    13 
    14                 Console.Read();
    15          }
    16 }

    通过查看IL代码,可以看到:

     1 .method private hidebysig static void  Main(string[] args) cil managed
     2 {
     3   .entrypoint
     4   // 代码大小       57 (0x39)
     5   .maxstack  2
     6   .locals init (bool V_0,
     7            object V_1,
     8            bool V_2)
     9   IL_0000:  nop
    10   IL_0001:  ldc.i4.0
    11   IL_0002:  stloc.0
    12   .try
    13   {
    14     IL_0003:  ldsfld     object ConsoleApplication1.MainApp/Program::lock4
    15     IL_0008:  dup
    16     IL_0009:  stloc.1
    17     IL_000a:  ldloca.s   V_0
    18     IL_000c:  call       void [mscorlib]System.Threading.Monitor::Enter(object,
    19                                                                         bool&)
    20     IL_0011:  nop
    21     IL_0012:  nop
    22     IL_0013:  ldstr      "i am wbq,i am testing lock"
    23     IL_0018:  call       void [mscorlib]System.Console::WriteLine(string)
    24     IL_001d:  nop
    25     IL_001e:  nop
    26     IL_001f:  leave.s    IL_0031
    27   }  // end .try
    28   finally
    29   {
    30     IL_0021:  ldloc.0
    31     IL_0022:  ldc.i4.0
    32     IL_0023:  ceq
    33     IL_0025:  stloc.2
    34     IL_0026:  ldloc.2
    35     IL_0027:  brtrue.s   IL_0030
    36     IL_0029:  ldloc.1
    37     IL_002a:  call       void [mscorlib]System.Threading.Monitor::Exit(object)
    38     IL_002f:  nop
    39     IL_0030:  endfinally
    40   }  // end handler
    41   IL_0031:  nop
    42   IL_0032:  call       int32 [mscorlib]System.Console::Read()
    43   IL_0037:  pop
    44   IL_0038:  ret
    45 } // end of method Program::Main

    第18行 Threading.Monitor::Enter,第37行 System.Threading.Monitor::Exit,关于IL代码的一些语法规则,我打算另外阐述。

        

  • 相关阅读:
    JS 实现日期信息增加年数,月数,天数
    ROW_NUMBER() OVER函数的基本用法,也可用于去除重复行
    Oracle存储过程返回游标实例详解
    PL/Sql 中创建、调试、调用存储过程
    HTTP 错误 404.13
    oracle查询多行数据合并成一行数据
    C# 实现list=list.OrderBy(q=>q.字段名).ToList(); 按多个字段排序
    [bcc32 Error] ws2def.h(231): E2238 Multiple declaration for 'sockaddr'
    [bcc32 Error] typeinfo.h(154): E2367 Can't inherit RTTI class from non-RTTI base 'exception'
    sql server 语法 MSDN
  • 原文地址:https://www.cnblogs.com/wangqiang3311/p/5873042.html
Copyright © 2011-2022 走看看