zoukankan      html  css  js  c++  java
  • C# lock用法

    lock 的目的很明确:就是不想让别人使用这段代码,体现在多线程情况下,只允许当前线程执行该代码区域,其他线程等待直到该线程执行结束;这样可以多线程避免同时使用某一方法造成数据混乱。

    lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断。它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待。

    一般定义如下:

    private static readonly object locker = new object();
     
    lock(locker)
    
    {//互斥段begin
    
         //Your Code...
    
    }//互斥段end
    
    其相当于如下代码:
    
    //System.Threading.Moniter.enter(Object),Moniter类提供同步访问//对象的机制,enter方法在指定对象上获取排他锁,之后其他线程不能再//次获取,直到释放
    
    Monitor.enter(locker); 
    {//互斥段begin
         //Your Code...
    }//互斥段end
    Monitor.exit(locker); //exit(Object)释放指定对象上的排他锁。
    //lock 语句的表达式必须表示一个引用类型的值。永远不会为 lock 语句中的表达式执行隐式装箱转换,因此,如果该表达式表示的是一个值类型的值,则会导致一个编译时错误。

     

    MSDN给出:我们lock的一般是对象,不是数值和字符串。

      1、为什么不能lock值类型

        比如lock(1)呢?lock本质上Monitor.Enter,Monitor.Enter会使值类型装箱,每次lock的是装箱后的对象。lock 其实是类似编译器的语法糖,因此编译器直接限制住不能lock值类型。退一万步说,就算能编译器允许你lock(1),但是 object.ReferenceEquals(1,1)始终返回false(因为每次装箱后都是不同对象),也就是说每次都会判断成未申请互斥锁,这样 在同一时间,别的线程照样能够访问里面的代码,达不到同步的效果。同理lock((object)1)也不行。

        2、Lock字符串

        那么lock("xxx")字符串呢?MSDN上的原话是:

    锁定字符串尤其危险,因为字符串被公共语言运行库 (CLR)“暂留”。 这意味着整个程序中任何给定字符串都只有一个实例,同一个对象表示了所有运行的应用程序域的所有线程中的该文本。因此,只要在应用程序进程中的任何 位置处具有相同内容的字符串上放置了锁,就将锁定应用程序中该字符串的所有实例。

        3、MSDN推荐的Lock对象

        通常,最好避免锁定 public 类型或锁定不受应用程序控制的对象实例。例如,如果该实例可以被公开访问,则 lock(this) 可能会有问题,因为不受控制的代码也可能会锁定该对象。这可能导致死锁,即两个或更多个线程等待释放同一对象。出于同样的原因,锁定公共数据类型(相比于 对象)也可能导致问题。

        而且lock(this)只对当前对象有效,如果多个对象之间就达不到同步的效果。

        而自定义类推荐用私有的只读静态对象,比如:

    private static readonly object obj = new object();

    为什么要设置成只读的呢?这是因为如果在lock代码段中改变obj的值,其它线程就畅通无阻了,因为互斥锁的对象变了,object.ReferenceEquals必然返回false。

    转载 :https://blog.csdn.net/smooth_tailor/article/details/52411359

    转载 :https://www.cnblogs.com/Janzen/p/5475519.html

    查看 :https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/lock-statement

  • 相关阅读:
    install_bugzilla
    R610 & R710 网卡问题
    总结开发者在合作过程中的典型交流方式
    vnc报错 font catalog is not properly configured
    eclipse插件安装
    extjs 点击链接到另一个页面 并激活另一个页面的指定tab
    centos c++ 找不到头文件mysql.h
    升级struts 2
    oracle 删除用户报错
    mysql 创建用户及授权
  • 原文地址:https://www.cnblogs.com/JourneyOfFlower/p/12849206.html
Copyright © 2011-2022 走看看