好文章,自己保存已备日后学习使用。原文出处:http://kenchell.blog.163.com/blog/static/26088309200821235841466/
lock 关键字可将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。
当一个lock已被占用时,在同一线程中执行的代码仍可以获取和释放该锁。但是,在其他线程中执行的代码在该锁被释放前是无法获得它的。
lock 语句的表达式必须表示一个引用类型的值。如果表达式表示的是一个值类型的值,则会导致一个编译时错误。
通常,如果要保护当前类,则 表达式 为 this
==================================================
lock后括号里面的值不是说把整个对象锁住,而是对他的标记进行了修改,使别的lock不能锁住他,这才是lock(object)的真面目.
那 我们lock住的是什么?是代码段,是lock后面大括号中代码段,这段代码让多个人执行不不被允许的.
那我们看lock(this), this是什么意思呢?可以说this只是这段代码域的标志(线程A中的lock需要等到线程B中lock释放后才开始运行,释放之前一直处于等待状态,这就是标志的表现.)
★让我们来了解一下,lock这段代码是怎么运行的.
lock语句根本使用的就是Moniter.Enter和Moniter.Exit,也就是说lock(this)时执行Moniter.Enter(this),大括号结束时执行Monitor.Exit(this).他的意义在于什么呢,对于任何一个对象来说,他在内存中的第一部分放置的是所有方法的地址,第二部分放着一个索引,他指向CLR中的SyncBlock Cache区域中的一个SyncBlock.什么意思呢?就是说,当你执行Monitor.Enter(Object)时,如果object的索引值为负数,就从SyncBlock Cache中选区一个SyncBlock,将其地址放在object的索引中。这样就完成了以object为标志的锁定,其他的线程想再次进行Monitor.Enter(object)操作,将获得object为正数的索引,然后就等待。直到索引变为负数,即线程使用Monitor.Exit(object)将索引变为负数。
P.S.在实际使用中Monitor还是不推荐,还是lock好的,Monitor需要加上很多try catch才能保证安全性,但lock却帮我们做了,而且lock看起来更优雅.
P.S.在静态方法中如何使用lock呢,由于我们没有this可用,所以我们使用lock(typeof(class))好了,Type也有相应的方法地址和索引,所以他也是可以来当作lock的标志的.
P.S.但微软不提倡是用public的object或者typeof()或者字符串这样的标志就是因为,如果你的public object在其他的线程中被null并被垃圾收集了,将发生不可预期的错误.
==================================================
例如:
class Account
{
int balance;
{
int balance;
public Account(int initial)
{
balance = initial;
}
{
balance = initial;
}
int Withdraw(int amount)
{
{
lock (this) //保护了当前类的方法Withdraw 线程
{
if (balance >= amount)
{
return amount;
}
}
}
}
{
if (balance >= amount)
{
return amount;
}
}
}
}
如果要保护 static 变量(或者如果临界区出现在类的静态方法中),则表达式为typeOf(class)
例如:
例如:
class AAA
{
public static void Add(object x) {
lock (typeof(AAA)) { //保护了AAA类的静态方法Add 线程
...
}
}
public static void Remove(object x) {
lock (typeof(AAA)) {
...
}
}
}
{
public static void Add(object x) {
lock (typeof(AAA)) { //保护了AAA类的静态方法Add 线程
...
}
}
public static void Remove(object x) {
lock (typeof(AAA)) {
...
}
}
}
======================================================
typeof 运算符用于获得某一类型的 System.Type 对象。
typeof 运算符用于获得某一类型的 System.Type 对象。
typeof(type) //type是 要获得其 System.Type 对象的类型。
不能重载 typeof 运算符。
若要获得一个表达式的运行时类型,可以使用 方法 GetType()