解决C# lock this问题

开发 后端
本文介绍C# lock this问题,以及解决方法,介绍其中Interlocked类是专门为多个线程共享的变量提供原子操作。

在以前编程中遇到lock问题总是使用lock(this)一锁了之,出问题后翻看MSDN突然发现下面几行字:通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 违反此准则:如果实例可以被公共访问,将出现C# lock this问题。如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题。由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock(“myLock”) 问题。来看看C# lock this问题:如果有一个类Class1,该类有一个方法用lock(this)来实现互斥:

  1. publicvoidMethod2()  
  2. {  
  3. lock(this)  
  4. {  
  5. System.Windows.Forms.MessageBox.Show("Method2End");  
  6. }  

如果在同一个Class1的实例中,该Method2能够互斥的执行。但是如果是2个Class1的实例分别来执行Method2,是没有互斥效果的。因为这里的lock,只是对当前的实例对象进行了加锁。

Lock(typeof(MyType))锁定住的对象范围更为广泛,由于一个类的所有实例都只有一个类型对象(该对象是typeof的返回结果),锁定它,就锁定了该对象的所有实例,微软现在建议,不要使用lock(typeof(MyType)),因为锁定类型对象是个很缓慢的过程,并且类中的其他线程、甚至在同一个应用程序域中运行的其他程序都可以访问该类型对象,因此,它们就有可能代替您锁定类型对象,完全阻止您的执行,从而导致你自己的代码的挂起。

锁住一个字符串更为神奇,只要字符串内容相同,就能引起程序挂起。原因是在.NET中,字符串会被暂时存放,如果两个变量的字符串内容相同的话,.NET会把暂存的字符串对象分配给该变量。所以如果有两个地方都在使用lock(“my lock”)的话,它们实际锁住的是同一个对象。到此,微软给出了个lock的建议用法:锁定一个私有的static 成员变量。

.NET在一些集合类中(比如ArrayList,HashTable,Queue,Stack)已经提供了一个供lock使用的对象SyncRoot,用Reflector工具查看了SyncRoot属性的代码,在Array中,该属性只有一句话:return this,这样和lock array的当前实例是一样的。ArrayList中的SyncRoot有所不同

  1. get  
  2. {  
  3. if(this._syncRoot==null)  
  4. {  
  5. Interlocked.CompareExchange(refthis._syncRoot,newobject(),null);  
  6. }  
  7. returnthis._syncRoot; 

其中Interlocked类是专门为多个线程共享的变量提供原子操作(如果你想锁定的对象是基本数据类型,那么请使用这个类),CompareExchange方法将当前syncRoot和null做比较,如果相等,就替换成new object(),这样做是为了保证多个线程在使用syncRoot时是线程安全的。集合类中还有一个方法是和同步相关的:Synchronized,该方法返回一个对应的集合类的wrapper类,该类是线程安全的,因为他的大部分方法都用lock来进行了同步处理,比如Add方法:

  1. publicoverridevoidAdd(objectkey,objectvalue)  
  2. {  
  3. lock(this._table.SyncRoot)  
  4. {  
  5. this._table.Add(key,value);  
  6. }  

这里要特别注意的是MSDN提到:从头到尾对一个集合进行枚举本质上并不是一个线程安全的过程。即使一个集合已进行同步,其他线程仍可以修改该集合,这将导致枚举数引发异常。若要在枚举过程中保证线程安全,可以在整个枚举过程中锁定集合:

  1. QueuemyCollection=newQueue();  
  2. lock(myCollection.SyncRoot){  
  3. foreach(ObjectiteminmyCollection){  
  4. //Insertyourcodehere.  
  5. }  

以上介绍C# lock this问题

【编辑推荐】

  1. 分析C#不安全代码
  2. 浅析C#调用ImageAnimator
  3. C#连接Access、SQL Server数据库
  4. 浅谈C#固定的和活动的变量
  5. 介绍C#中的值类型
责任编辑:佚名 来源: 博客园
相关推荐

2021-06-11 00:09:20

C#爬虫版本

2009-08-10 13:49:50

C# txt文件

2009-08-11 10:42:14

C#算法

2009-08-13 13:04:29

C# lock关键字

2009-08-26 15:16:29

C# lock关键字

2009-08-13 17:25:18

C# Convert类

2009-08-07 14:47:23

C#路径问题

2009-08-26 18:13:55

C#多线程lock

2011-04-25 14:42:10

C#lock

2009-08-11 09:40:22

张老师的生日问题C#算法

2012-02-02 14:34:37

C# Socket

2024-09-17 17:50:28

线程线程安全代码

2009-09-15 17:46:08

C#绑定句柄无效

2009-08-06 16:01:30

C#接口成员

2009-09-03 14:38:28

C#日期格式化C#日期格式

2009-08-28 10:14:45

C#内存泄露

2009-09-02 14:30:35

C#换行符号

2009-08-05 08:42:41

C#中用Oracle执DataSet

2011-04-25 15:15:00

C#

2011-04-21 15:04:30

C#
点赞
收藏

51CTO技术栈公众号