C#之lock关键字 lock锁定语句
2014-04-24 10:06
260 查看
lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。下面的示例包含一个lock 语句。
class Account { decimal balance; private Object thisLock = new Object(); public void Withdraw(decimal amount) { lock (thisLock) { if (amount > balance) { throw new Exception("Insufficient funds"); } balance -= amount; } } }lock 关键字可确保当一个线程位于代码的临界区时,另一个线程不会进入该临界区。如果其他线程尝试进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放提供给 lock 关键字的参数必须为基于引用类型的对象,该对象用来定义锁的范围。在上面的示例中,锁的范围限定为此函数,因为函数外不存在任何对对象lockThis 的引用。如果确实存在此类引用,锁的范围将扩展到该对象。严格地说,提供的对象只是用来唯一地标识由多个线程共享的资源,所以它可以是任意类实例。然而,实际上,此对象通常表示需要进行线程同步的资源。例如,如果一个容器对象将被多个线程使用,则可以将该容器传递给 lock,而 lock 后面的同步代码块将访问该容器。只要其他线程在访问该容器前先锁定该容器,则对该对象的访问将是安全同步的。通常,最好避免锁定 public 类型或锁定不受应用程序控制的对象实例。例如,如果该实例可以被公开访问,则lock(this) 可能会有问题,因为不受控制的代码也可能会锁定该对象。这可能导致死锁,即两个或更多个线程等待释放同一对象。出于同样的原因,锁定公共数据类型(相比于对象)也可能导致问题。锁定字符串尤其危险,因为字符串被公共语言运行时 (CLR)“暂留”。这意味着整个程序中任何给定字符串都只有一个实例,就是这同一个对象表示了所有运行的应用程序域的所有线程中的该文本。因此,只要在应用程序进程中的任何位置处具有相同内容的字符串上放置了锁,就将锁定应用程序中该字符串的所有实例。因此,最好锁定不会被暂留的私有或受保护成员。lock 关键字在块的开始处调用Enter,而在块的结尾处调用Exit。ThreadInterruptedException 引发,如果 Interrupt 中断等待输入lock 语句的线程。通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构lock (this)、lock (typeof (MyType)) 和lock ("myLock") 违反此准则:如果实例可以被公共访问,将出现 lock (this) 问题。如果 MyType 可以被公共访问,将出现lock (typeof (MyType)) 问题。由于进程中使用同一字符串的任何其他代码都将共享同一个锁,所以出现 lock("myLock") 问题。最佳做法是定义 private 对象来锁定, 或private static 对象变量来保护所有实例所共有的数据。在 lock 语句的正文不能使用 await 关键字。可以使用 as 运算符执行转换的某些类型在兼容之间的引用类型或可以为 null 的类型。下面的代码提供了一个示例。C#复制
class csrefKeywordsOperators { class Base { public override string ToString() { return "Base"; } } class Derived : Base { } class Program { static void Main() { Derived d = new Derived(); Base b = d as Base; if (b != null) { Console.WriteLine(b.ToString()); } } } }备注as 运算符类似于强制转换操作。但是,因此,如果转换是不可能的,as 返回null 而不引发异常。请看下面的示例:复制
expression as type代码与下面的表达式是等效的,但 expression 变量只计算一次。复制
expression is type ? (type)expression : (type)null请注意 as 运算符执行只引用转换、nullable 转换和装箱转换。as 运算符不能执行其他转换,如用户定义的转换,应是通过使用转换的表达式。示例C#复制
class ClassA { }class ClassB { }class MainClass{ static void Main() { object[] objArray = new object[6]; objArray[0] = new ClassA(); objArray[1] = new ClassB(); objArray[2] = "hello"; objArray[3] = 123; objArray[4] = 123.4; objArray[5] = null; for (int i = 0; i < objArray.Length; ++i) { string s = objArray[i] as string; Console.Write("{0}:", i); if (s != null) { Console.WriteLine("'" + s + "'"); } else { Console.WriteLine("not a string"); } } }}/*Output:0:not a string1:not a string2:'hello'3:not a string4:not a string5:not a string*/
相关文章推荐
- “锁定”语句 lock(C# 参考)
- C# Lock 关键字锁定静态变量和非静态变量的区别
- Lock“锁定”语句(C# 参考)
- C# 使用lock关键字lock不同的对象
- [C#参考]锁定lock
- C#中的lock关键字(初识)
- 用MSIL剥开C#的外衣(一):方法参数ref、out、params和lock、for和foreach关键字
- 理解c#多线程中的lock关键字
- C#笔记21:多线程之线程同步中的锁定lock、Monitor
- lock 语句(C# )
- C#中的lock关键字
- C#中的lock关键字有何用!
- C# lock关键字叙述
- 减小锁定的粒度:C#实现基于关键字(key)的锁定
- C#线程同步技术(一) lock 语句
- C#中Monitor类、Lock关键字和Mutex类
- C#基础—— check、lock、using语句归纳
- (转载)C#中的lock关键字
- C#中的lock关键字
- C#系列教程——lock语句定义及使用