.NET中的lock
来源:互联网 发布:淘宝威客 编辑:程序博客网 时间:2024/05/16 16:05
lock 关键字可将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。此语句的形式如下:
lock(expression) statement_block
其中:
expression
指定要锁定的对象。expression 必须是引用类型。
通常,如果要保护实例变量,则 expression 为 this;如果要保护 static 变量(或者如果临界区出现在给定类的静态方法中),则 expression 为 typeOf (class)。
statement_block
临界区的语句。
备注
lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入一个锁定代码,则它将在释放该对象前一直等待(块)。
8.12 lock 语句对 lock 进行了讨论。
示例 1
下例显示的是在 C# 中使用线程的简单示例。
// statements_lock.cs
using System;
using System.Threading;
class ThreadTest
{
public void runme()
{
Console.WriteLine("runme called");
}
public static void Main()
{
ThreadTest b = new ThreadTest();
Thread t = new Thread(new ThreadStart(b.runme));
t.Start();
}
}
输出
runme called
示例 2
下例使用线程和 lock。只要 lock 语句存在,语句块就是临界区并且 balance 永远不会是负数。
// statements_lock2.cs
using System;
using System.Threading;
class Account
{
int balance;
Random r = new Random();
public Account(int initial)
{
balance = initial;
}
int Withdraw(int amount)
{
// This condition will never be true unless the lock statement
// is commented out:
if (balance < 0)
{
throw new Exception("Negative Balance");
}
// Comment out the next line to see the effect of leaving out
// the lock keyword:
lock (this)
{
if (balance >= amount)
{
Console.WriteLine("Balance before Withdrawal : " + balance);
Console.WriteLine("Amount to Withdraw : -" + amount);
balance = balance - amount;
Console.WriteLine("Balance after Withdrawal : " + balance);
return amount;
}
else
{
return 0; // transaction rejected
}
}
}
public void DoTransactions()
{
for (int i = 0; i < 100; i++)
{
Withdraw(r.Next(1, 100));
}
}
}
class Test
{
public static void Main()
{
Thread[] threads = new Thread[10];
Account acc = new Account (1000);
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(acc.DoTransactions));
threads[i] = t;
}
for (int i = 0; i < 10; i++)
{
threads[i].Start();
}
}
}
2 {
3 private int i = 0;
4 public void Test()
5 {
6 Thread t1 = new Thread(Thread1);
7 Thread t2 = new Thread(Thread2);
8 t1.Start();
9 t2.Start();
10 }
11 public void Thread1()
12 {
13 lock (this)
14 {
15 Console.WriteLine(this.i);
16 Thread.Sleep(1000);
17 Console.WriteLine(this.i);
18 }
19 }
20 public void Thread2()
21 {
22 Thread.Sleep(500);
23 this.i = 1;
24 Console.WriteLine("Change the value in locking");
25 }
26 }
27 public class ThreadTest2
28 {
29 private int i = 0;
30 public void Test()
31 {
32 Thread t1 = new Thread(Thread1);
33 Thread t2 = new Thread(Thread2);
34 t1.Start();
35 t2.Start();
36 }
37 public void Thread1()
38 {
39 lock (this)
40 {
41 Console.WriteLine(this.i);
42 Thread.Sleep(1000);
43 Console.WriteLine(this.i);
44 }
45 }
46 public void Thread2()
47 {
48 lock (this)
49 {
50 Thread.Sleep(500);
51 this.i = 1;
52 Console.WriteLine("Can't change the value in locking");
53 }
54 }
55 }
两段程序有什么区别吗?看看吧,ThreadTest2.Thread2()中多了一个lock(this)却产生了不同的结果
本想在案例一中lock住this对象,让其他的线程不能操作,可是事情不是像我们想象的那样lock(this)是lock this的意思.this中的属性依然能够被别的线程改变.那我们lock住的是什么?是代码段,是lock后面大括号中代码段,这段代码让多个人执行不不被允许的.那返回头来在看lock(this),this是什么意思呢?可以说this知识这段代码域的标志,看看案例二中Thread2.Thread2就明白了,Thread2中的lock需要等到Thread1种lock释放后才开始运行,释放之前一直处于等待状态,这就是标志的表现.
好吧,让我们来了解一下,lock这段代码是怎么运行的.lock语句根本使用的就是Monitor.Enter和Monitor.Exit,也就是说lock(this)时执行Monitor.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)将索引变为负数。
如果明白了Monitor.Enter的原理,lock当然不再话下.当然lock后括号里面的值不是说把整个对象锁住,而是对他的一个值进行了修改,使别的lock不能锁住他,这才是lock(object)的真面目.
但在实际使用中Monitor还是不推荐,还是lock好的,Monitor需要加上很多try catch才能保证安全性,但lock却帮我们做了,而且lock看起来更优雅.
在静态方法中如何使用lock呢,由于我们没有this可用,所以我们使用typeof(this)好了,Type也有相应的方法地址和索引,所以他也是可以来当作lock的标志的.
但微软不提倡是用public的object或者typeof()或者字符串这样的标志就是因为,如果你的public object在其他的线程中被null并被垃圾收集了,将发生不可预期的错误.
- .NET中的lock
- NET中的lock(C#版本)
- .net Lock
- .net double lock
- .net lock的使用方法
- .net Lock用法
- ORACLE 中的lock 机制
- postgreSQL 中的 Lock
- postgresql中的spin lock
- hibernate中的optimistic-lock(...
- hibernate中的optimistic-lock(...
- sqlite中的lock
- Lucene3中的Lock锁
- X86中的LOCK命令
- C#中的lock关键字
- lock 多线程中的用法
- C#中的lock关键字
- C#中的lock
- SQL Server 中图片和文件的存取(C#.NET)
- Hello CSDN Blog's World
- ARM学习笔记(一)
- ConnectionString gather
- Eclipse RCP 学习过程(二)
- .NET中的lock
- 感谢happyyourlife-DevExpress.ExpressQuantumGrid.Suite.v5.9 FS在BCB6下安装过程实录
- 计算机网络笔记第二章 应用层tcpip primer plus 第十五章
- Out-File 帮助信息
- javascript小技巧(转自DooIT)http://www.cnblogs.com/ttyp/archive/2004/11/15/63900.html
- MyEclipse注册码
- C 基础 (整形,字符型,浮点型)
- 飘云QQ宣布终止后续开发 称不懂游戏规则玩不起
- C#通过TCP传送结构体