`
hududanyzd
  • 浏览: 777565 次
文章分类
社区版块
存档分类
最新评论

C#中为多线程变量提供原子操作的类Interlocked

 
阅读更多

最近在工作中经常用到了多线程来处理问题,但是关于多线程共享变量的问题就需要解决了。还好.net为我们提供了InterLocked类,它可是微软专门为多个线程共享的变量提供原子操作的类。我们经常用到的方法之一是Interlocked.Increment()和Interlocked.Decrement()。

如下是MSDN上关于这2个方法的介绍:

IncrementDecrement 方法递增或递减变量并将结果值存储在单个操作中。在大多数计算机上,增加变量操作不是一个原子操作,需要执行下列步骤:

  1. 将实例变量中的值加载到寄存器中。

  2. 增加或减少该值。

  3. 在实例变量中存储该值。

如果不使用 IncrementDecrement,线程会在执行完前两个步骤后被抢先。然后由另一个线程执行所有三个步骤。当第一个线程重新开始执行时,它覆盖实例变量中的值,造成第二个线程执行增减操作的结果丢失。

关于Interlocked类的更详细介绍我们可以参考MSDN上的介绍:

http://msdn.microsoft.com/zh-cn/library/system.threading.interlocked%28v=VS.100%29.aspx。

其实我们还有另外一直方法在多线程中锁定变量或者文件等进行操作,如下所示:

lock ()
{

//do something...

}

通常,应避免锁定 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. }
  7. }

如果在同一个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;
要特别注意的是MSDN提到:从头到尾对一个集合进行枚举本质上并不是一个线程安全的过程。即使一个集合已进行同步,其他线程仍可以修改该集合,这将导致枚举数引发异常。若要在枚举过程中保证线程安全,可以在整个枚举过程中锁定集合:
  1. QueuemyCollection=newQueue();
  2. lock(myCollection.SyncRoot){
  3. foreach(ObjectiteminmyCollection){
  4. //Insertyourcodehere.
  5. }
  6. }



分享到:
评论

相关推荐

    c# 线程(thread)同步处理

    .NET平台上的线程同步的问题线程之间共享的变量访问的同步,它的操作时原子操作,且被线程共享.你可以通过Interlocked.Increment 或 Interlocked.Decrement来增加或减少共享变量.它的有点在于是原子操作,也就是说...

    深入多线程之:深入分析Interlocked

    在大多数计算机上,增加变量操作不是一个...Interlocked可以为多个线程共享的变量提供原子操作。  Interlocked.Increment:以原子操作的形式递增指定变量的值并存储结果。 Interlocked.Decrement以原子操作的形式递减

    c#.net多线程编程教学——线程同步

    考虑一种我们经常遇到的情况:有一些全局变量和共享的类变量,我们需要从不同的线程来更新它们,可以通过使用System.Threading.Interlocked类完成这样的任务,它提供了原子的,非模块化的整数更新操作。 还有你可以...

    C#线程锁介绍源码

    Interlocked 类提供了同步对多个线程共享的变量的访问的方法。如果该变量位于共享内存中,则不同进程的线程就可以使用该机制。互锁操作是原子的,即整个操作是不能由相 同变量上的另一个互锁操作所中断的单元。这在...

    C#中使用Interlocked进行原子操作的技巧

    使用.NET提供的Interlocked类可以对一些数据进行原子操作,看起来似乎跟lock锁一样,但它并不是lock锁,它的原子操作是基于CPU本身的,非阻塞的,所以要比lock的效率高

    C#实现多线程的同步方法实例分析

    本文主要描述在C#中线程同步的方法。线程的基本概念网上资料也很多就不再赘述了。直接接入 主题,在多线程开发的应用中,线程同步是不可避免的。在.Net框架中,实现线程同步主要通过以下的几种方式来实现,在MSDN的...

    .NET中保证线程安全的高级方法Interlocked类使用介绍

    主要介绍了.NET中保证线程安全的高级方法Interlocked类使用介绍,Interlocked类可以为为多个线程共享的变量提供原子操作,需要的朋友可以参考下

    C#实现多线程的同步方法详解

    本文主要描述在C#中线程同步的方法。线程的基本概念网上资料也很多就不再赘述了。直接接入主题,在多线程开发的应用中,线程同步是不可避免的。在.Net框架中,实现线程同步主要通过以下的几种方式来实现,在MSDN的...

    NET多线程同步方法详解

    .NET多线程同步方法详解(一):自由锁(InterLocked) 本文主要描述在C#中线程同步的方法。线程的基本概念网上资料也很多就不再赘述了。直接接入主题,在多线程开发的应用中,线程同步是不可避免的。在.Net框架中,...

    C#使用Interlocked实现线程同步

    通过System.Threading命名空间的Interlocked类控制计数器,从而实现进程 的同步。Iterlocked类的部分方法如下表: 示例,同时开启两个线程,一个写入数据,一个读出数据 代码如下:(但是运行结果却不是我们想象的...

    C#多线程编程中的锁系统(二)

    主要介绍了C#多线程编程中的锁系统(二),本文讲解了volatile、Interlocked、ReaderWriterLockSlim等升级锁和原子操作的使用实例,需要的朋友可以参考下

    C#中实现线程同步lock关键字的用法详解

    如果需要对它们进行互斥访问限制,可以使用System.Threading.Interlocked类提供的方法,这个类是提供原子操作的。 3. lock(this)的使用要慎重。共有类型中使用lock(this),如果新的对象被创建并加锁,极易造成死锁。

    C#5.0本质论第四版(因文件较大传的是百度网盘地址)

    19.1.6 使用System.Threading.Interlocked类 570 19.1.7 多个线程时的事件通知 571 19.1.8 同步设计最佳实践 572 19.1.9 更多的同步类型 573 19.1.10 线程本地存储 580 19.2 计时器 583 ...

    C#不同锁性能比较

    将C#中的Lock/Monitor/InterLocked用代码示例做性能比较

    CLR.via.C#.(中文第3版)(自制详细书签)

    CLR.via.C#.(中文第3版)(自制详细书签)Part2 CLR via C#(第3版) Jeffrey Richter 著 周靖 译 出版时间:2010年09月 页数:800 介绍 享有全球盛誉的编程专家Jeffrey Richter,这位与Microsoft .NET开发团队...

    CLR.via.C#.(中文第3版)(自制详细书签)Part2

    CLR.via.C#.(中文第3版)(自制详细书签)Part2 CLR via C#(第3版) Jeffrey Richter 著 周靖 译 出版时间:2010年09月 页数:800 介绍 享有全球盛誉的编程专家Jeffrey Richter,这位与Microsoft .NET开发团队合作...

Global site tag (gtag.js) - Google Analytics