C# lock 为什么要设置成只读

首先给出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。

时间: 10-25

C# lock 为什么要设置成只读的相关文章

C#项目打包后安装的桌面快捷方式图标怎么设置成自己想要的图标

#项目打包后安装的桌面快捷方式图标怎么设置成自己想要的图标 2012-08-25 09:11匿名 | 浏览 3286 次 C#编程 C#项目用vs2005自带的工具打包后安装的桌面快捷方式图标怎么设置成自己想要的图标,就想QQ安装之后在桌面的快捷方式一样 2012-08-25 09:21网友采纳 在创建快捷方式的时候是可以指定图标的啊.当然你最好把那图标文件(扩展名是ico)放在打包的文件夹中,不然你是不能指定的.

将Win7笔记本设置成WiFi热点(无线路由器)

查看是否能启动WiFi网卡: S1:运行cmd命令,打开命令提示符窗口(以管理员身份运行). S2:在命令行输入:netsh wlan show drivers. 若"支持的承载网络"后为"是",则可以启用虚拟wifi网卡:"否"则不可以. 启用虚拟WiFi网卡: S1:在命令行中输入:netsh wlan set hostednetwork mode=allow ssid=用户名key=密码(mode:是否启用虚拟WiFi网卡,allow为启用

eclipse 背景色调整,设置成护眼色(豆沙绿)

eclipse 背景色调整--设置成护眼色 第一步: windows->peferences->General->Editors->Text EditorAppearance color options: 选择Background color,去掉System default  点击color框,进入颜色设置窗口. 第二步: 将色调,饱和度,亮度调整为85, 123, 205(或者 85; 90; 205)点击添加到自定义颜色,点击确定,回到主界面后,点击应用即可

powerdesigner中把用例关系线设置成直线

powerdesigner中默认参与者与用例之间的关系线是折线,如图: 如果想设置成直线显示,如下图: 则需要做设置: Tools-->Display Preferences 选择最后一项 3. 选择Format 4. 点"modify",选corners中的最后一项,如图: 就ok了. 不过不知道是不是我这个版本的问题(16.5),设置完后原来的线会显示成弯线,要把原来的关系线删除掉再重新建立一次关系才会显示直线.

view设置成圆角

有时候我们需要把图片.textview等view设置成圆角: 需要Core Graphics框架 头文件: #import <QuartzCore/QuartzCore.h> code: view.layer.borderWidth = 1; view.layer.cornerRadius = 6; view.layer.masksToBounds = YES; view设置成圆角,布布扣,bubuko.com

Android入门--实现选择并编辑图片设置成头像

在很多时候需要更换头像或者选择图片,所以这里总结下实现选择并编辑图片然后设置成头像的方法,下面开始: 整体结构如下:  创建项目,命名为ChooseImage_test 创建完成,在drawable-hdip文件夹中添加一张默认头像图片,用于在用户选择头像之前显示或者当用户未选择头像时做默认头像:  创建布局文件 这里为了贴合实际,整个页面就只有一个ImageView,当然现在是矩形的ImageView显示头像,后面会结合设置圆形头像的功能实现圆形头像选择功能 <RelativeLayout x

桌面上嵌入窗口(桌面日历)原理探索(将该窗口的Owner设置成桌面的Shell 窗口,可使用SetWindowLong更改窗口的GWL_HWNDPARENT,还要使用SetWindowPos设置Z-Order)

今天在QQ群里有人问怎样实现将自己的窗口嵌入桌面,让它和桌面融为一体,就像很多桌面日历软件那样. 我当时想到的就是建立一个Child  Window,将他的父窗口设置成桌面Shell窗口就可以了.但是后来想想觉得不对,因为很多桌面日历窗口都有半透明和阴影效果,明显是用Layered Window实现的,而大家知道Layered Window一定要用Pop Up Window才能实现的. 那么如何用Pop up Window实现这种效果呢? 这里关键的一点就是要将该窗口的Owner设置成桌面的Sh

Linux的/etc/inittab文件中init级别设置成6(重启)或者不支持级别的解决方法

如果不小心将/etc/inittab文件中的init级别设置成6(重启)或者不支持级别,系统就不能正常启动.本博客讲解如何通过Grub来解决这个问题. 1. 在Linux启动过程中,按Esc键进入Grub界面 2. 按e修改当前Linux系统的配置 3. 选择第二行,按e键,并按如下步骤执行 1)在出现的命令行后加1(单用户模式): 2)按Enter键接收操作并后退到当前Linux配置页面: 3)按b重启Linux. 4. 重启后进入Linux系统,修改/etc/inittab文件.将init级

Tomcat设置成NIO时,使用的线程池

设置成NIO时, <Connector port="8088" protocol="org.apache.coyote.http11.Http11NioProtocol" ... maxThreads属性是没用的,因为默认使用的是NIO的线程池,除非你使用了executor属性,设置了特定的线程池 本人已进行过测试,使用Http11NioProtocol,同时将maxThreads设成200,让后进行1000个并发请求,仍然可以通过 正常情况下,设置成http