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

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

  1. Excel2007给表格设置成只读加密属性 让他人无法修改

    在制作一些报表和公司的表格时,我们常常需要给Excel表格加密或者设置成只读属性来加以防护这些重要表格.给表格加密可以预防他人无法打开表格,只有通过输入正确的密码后才可以正常打开.设置成只读的话,可以 ...

  2. Oracle设置表只读-alter table xxx read only

    11g以前,当需要设置一个表只读时,我们通过赋予某些用户select权限.但对于表的owner来说,还是可以读写的. 从Oracle 11g开始,我们可以通过一下命令设置表只读或可读可写: alter ...

  3. mysql主键设置成auto_increment时,进行并发性能測试出现主键反复Duplicate entry 'xxx' for key 'PRIMARY'

    mysql主键设置成auto_increment时,进行并发性能測试出现主键反复Duplicate entry 'xxx' for key 'PRIMARY' 解决方法: 在my.cnf的[mysql ...

  4. java-同步控制及不可变设置(只读访问)

    1.还是直接上代码简单了解一下: package com.synchronize.test; import java.util.ArrayList; import java.util.Collecti ...

  5. MySQL数据库设置为只读及测试【转】

    转自 mysql只读模式的设置方法与实验 - yumushui的专栏 - CSDN博客http://blog.csdn.net/yumushui/article/details/41645469 在M ...

  6. nginx设置成开机自动启动服务

    1.nginx的安装目录 /usr/local/nginx 启动nginx cd /usr/local/nginx/sbin./nginx 更改配置重启nginxcd /usr/local/nginx ...

  7. C++构造函数/析构函数 设置成private的原因

    C++构造函数/析构函数 设置成private的原因 标签(空格分隔): c/c++ 将构造函数,析构函数声明为私有和保护的,那么对象如何创建? 已经不能从外部调用构造函数了,但是对象必须被构造,应该 ...

  8. Mac下输入法总是默认中文,怎么设置成英文的?

    最近一同事在DreamWeaver里,写CSS样式的时候,默认总是中文,切到别的窗口,再切回来,就变成中文了,总要按一下切换键,时间长了特别烦人. 在网上找了一些方法,最后找到一个有效的. 总结一下就 ...

  9. 关于网页控件设置成disabled以后,提交不到后台的问题

    在开发的时候经常遇到这样的问题,就是需要设置某个控件不可编辑,这个控件可能是一个input文本框,可能是一个select下拉列表 遇到这样的问题,一般有两种处理方法 第一种是将input 控件添加 d ...

随机推荐

  1. 记一次root用户在本地登录及SSH连接均遭遇permission denied的问题排查经过

    某日一位老师反映,机房的6号节点无法登录了.一开始以为是为节点防火墙配置IP白名单时忘记了加进去,但随后发现此节点并未进行白名单配置,密码也一直未有变更,于是在自己的电脑上连接,发现终端里很快显示出了 ...

  2. redis编译和安装出现错误

    redis编译到时候出现错误,记录一下原因 1.下载redis,https://redis.io/download ,一般选择稳定版本,稳定版的版本号是偶数,当前最新版本是5.0.4,Linux可直接 ...

  3. Summer training #8

    A: B:按题意直接暴力找符合题意的数的个数 #include <bits/stdc++.h> #include <cstring> #include <iostream ...

  4. CSS基础学习-13.CSS 浮动

    如果前一个元素设置浮动属性,则之后的元素也会继承float属性,我觉得这里说是继承不太对,可以理解为会影响到之后的元素,所以在设置浮动元素之后的元素要想不被影响就需要清除浮动.元素设置左浮动,则清除左 ...

  5. --print-defaults打印mysqld启动加载配置

    Mysql启动配置文件加载路径     Mysql可以读取到的配置文件         /etc/my.cnf         /etc/mysql/my.cnf         /usr/local ...

  6. TXNLP 20-33

    文本处理的流程 # encoding=utf-8 import jieba import warnings # 基于jieba的分词 seg_list = jieba.cut("贪心学院专注 ...

  7. JDK8日期处理API(转)

    转载地址:http://www.cnblogs.com/comeboo/p/5378922.html 转载地址:http://blog.csdn.net/hspingcc/article/detail ...

  8. Amazon Redshift and the Case for Simpler Data Warehouses

    Redshift是Amazon一个商业产品上的进化 但并不是技术的进化,他使用的无非都是传统数仓领域的技术 如果说创新,就是大量使用Amazon本身的云服务的云原生架构,大大提升的产品的迭代速度,可维 ...

  9. 初识 ZeroMQ

    由于网上和官方的ZeroMQ主要是讲解和说明大都是基于C.PHP.Java偏偏.Net的很少,可能你看完80多页的官方文档仍被C代码搞的晕晕乎乎的,我这里就将资料收集整理成几篇博文同时用c#重新实现D ...

  10. 关于vue-resource 跨域请求的异常处理方法

    当你启动一个vue项目时,项目会运行在一个webpack的服务上,所以此时去访问其他端口或者是其他地址时,属于跨域请求,故会报异常. has been blocked by CORS policy: ...