前几天与同事激烈讨论了一下,有一点收获,记录起来。

首先给出MSDN的定义:

lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断。这是通过在代码块运行期间为给定对象获取互斥锁来实现的。

先来看看执行过程,代码示例如下:

假设线程A先执行,线程B稍微慢一点。线程A执行到lock语句,判断obj是否已申请了互斥锁,

判断依据是逐个与已存在的锁进行object.ReferenceEquals比较(此处未加证实),如果不存

在,则申请一个新的互斥锁,这时线程A进入lock里面了。

这时假设线程B启动了,而线程A还未执行完lock里面的代码。线程B执行到lock语句,检查到obj

已经申请了互斥锁,于是等待;直到线程A执行完毕,释放互斥锁,线程B才能申请新的互斥锁并执行

lock里面的代码。

接下来说一些该lock什么对象。

为什么不能lock值类型,比如lock(1)呢?lock本质上Monitor.Enter,Monitor.Enter会使值类型装箱,

每次lock的是装箱后的对象。lock其实是类似编译器的语法糖,因此编译器直接限制住不能lock值类型。

退一万步说,就算能编译器允许你lock(1),但是object.ReferenceEquals(1,1)始终返回false(因为

每次装箱后都是不同对象),也就是说每次都会判断成未申请互斥锁,这样在同一时间,别的线程照样能

够访问里面的代码,达不到同步的效果。同理lock((object)1)也不行。

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

锁定字符串尤其危险,因为字符串被公共语言运行库 (CLR)“暂留”。 这意味着整个程序中任何给定字符串

都只有一个实例,就是这同一个对象表示了所有运行的应用程序域的所有线程中的该文本。因此,只要在应用

程序进程中的任何位置处具有相同内容的字符串上放置了锁,就将锁定应用程序中该字符串的所有实例。

通常,最好避免锁定 public 类型或锁定不受应用程序控制的对象实例。例如,如果该实例可以被公开访问,

则 lock(this) 可能会有问题,因为不受控制的代码也可能会锁定该对象。这可能导致死锁,即两个或更多个线

程等待释放同一对象。出于同样的原因,锁定公共数据类型(相比于对象)也可能导致问题。而且lock(this)

只对当前对象有效,如果多个对象之间就达不到同步的效果。

lock(typeof(Class))与锁定字符串一样,范围太广了。

某些系统类提供专门用于锁定的成员。例如,Array 类型提供 SyncRoot。许多集合类型也提供 SyncRoot。

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

private static readonly object obj = new object();

为什么要设置成只读的呢?这时因为如果在lock代码段中改变obj的值,其它线程就畅通无阻了,因为互斥锁的

对象变了,object.ReferenceEquals必然返回false。

最新文章

  1. nginx、fastCGI、php-fpm关系梳理(转)
  2. 临时解决系统中大量的TIME_WAIT连接
  3. pv命令监控Linux命令的执行进度
  4. RDLC系列之三 图片显示
  5. USACO 3.3 fence 欧拉回路
  6. mongoDB 下载/安装/客户端笔记
  7. 最最基层的ajax交互代码jquery+java之间的json跨域传递以及java的json代码返回
  8. IOS缓存之NSCache缓存
  9. HDU 4746 (莫比乌斯反演) Mophues
  10. UDP模块(黑胶体)
  11. Windows Phone开发(15):资源
  12. ASP.NET Web API中的JSON和XML序列化
  13. hibernate实体对象的三种状态:自由状态,持久状态,游离状态.
  14. 设计模式 | 装饰模式(decorator)
  15. linux mailbox模型
  16. Java锁与CAS
  17. javascript 禁用 右键 按键 禁用开发者工具
  18. RabbitMQ基本理论
  19. 手机(Android)资源
  20. 在阿里云Windows Server 上部署ASP .NET CORE2.0项目

热门文章

  1. Class Object
  2. sql 判断两个时间段是否有交集
  3. IE浏览器 下面的文本框,获得焦点后无法输入内容
  4. 深入浅出ES6(三):生成器 Generators
  5. LINQ——语言级集成查询入门指南(1)
  6. 欧拉工程第66题:Diophantine equation
  7. Unix编程之size_t、ssize_t
  8. 怎样加快master数据库的写操作?分表原则!将表水平划分!或者添加写数据库的集群
  9. Delphi 中的 procedure of object (类方法存在一个隐藏参数self),简单深刻 good
  10. 在PowerDesigner中设计物理模型1——表和主外键