首先给出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. FASTCGI/CGI

    在了解这两个协议之前,我们先谈一下动态网页 动态网页 是指跟静态网页相对的一种网页编程技术.静态网页,随着html代码的生成,页面的内容和显示效果就基本上不会发生变化了--除非你修改页面代码.而动态网 ...

  2. oracle下关于table的常用sql整理

    创建表,create TABLE table( 列名称1 数据类型1, 列名称2 数据类型2, 列名称3 数据类型3, ......); eg: create table TABLE_24751( i ...

  3. UVa540 Team Queue(队列queue)

    队列 STL队列定义在头文件<queue>中, 用“ queue<int>s ” 方式定义, 用push()和pop()进行元素的入队和出队操作, front()取队首元素(但 ...

  4. (三) 结构化查询语言SQL——1

    1. SQL概述 SQL,结构化查询语言,重要性不必在赘述了,基本上开发软件没有不用到的,此外在一些大数据也有广泛的应用.SQL主要包含数据定义语言(DDL).数据操纵语言(DML)以及数据控制语言( ...

  5. Zabbix Server设置主机监控

  6. Linux启动原理

    Linux系统启动原理 #!此文章参考某godedu,用于复习查看 centos6系统 centos6系统启动过程 1. 加载 BIOS 的硬件信息,跟据设定取得第一个可开机引导设置,如:光驱,硬盘, ...

  7. Ubuntu 安装openmpi

    Ubuntu14.04TLS安装openmpi参考:https://likymice.wordpress.com/2015/03/13/install-open-mpi-in-ubuntu-14-04 ...

  8. 题解 比赛 match

    比赛 match Description 有 N 支队伍打比赛.已知有如下条件: • 每支队伍恰好打了 4 场比赛 • 对于一场比赛,如果是平局,双方各得 1 分:否则胜者得 3 分,负者不得分 给定 ...

  9. 题解 【USACO 4.2.1】草地排水

    [USACO 4.2.1]草地排水 Description 在农夫约翰的农场上,每逢下雨,贝茜最喜欢的三叶草地就积聚了一潭水.这意味着草地被水淹没了,并且小草要继续生长还要花相当长一段时间.因此,农夫 ...

  10. android的ant编译打包

    Android本身是支持ant打包项目的,并且SDK中自带一个build.xml文件. 通过该文件,可以对文件进行编译.打包.安装等.并且支持多种方式打包,如debug或者release. 一般的,可 ...