• 还好.net为我们提供了InterLocked类,它可是微软专门为多个线程共享的变量提供原子操作的类。我们经常用到的方法之一是Interlocked.Increment()和Interlocked.Decrement()。 如下是MSDN上关于这2个方法的介绍: ...

               最近在工作中经常用到了多线程来处理问题,但是关于多线程共享变量的问题就需要解决了。还好.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. }  

    如果在同一个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# 原子操作理解 2019-09-27 03:15:35
    C#内置提供的原子操作 Interlocked.Increment:以原子操作的形式递增指定变量的值并存储结果。 Interlocked.Decrement:以原子操作的形式递减指定变量的值并存储结果。 Interlocked.Add:以原子操作的形式,添加两...
  • 结构类型 结构类型适用于早应用程序中对数学、几何以及“原子”实体模型。结构是用户自定义的类型,然而,结构不只是一组名称值对。...在C#中,使用struct关键字来创建结构。定义一个新的Point,它定义...
  • C#原子操作 Lock用法 2015-11-01 23:03:02
    C# 理解lock 一. 为什么要lock,lock了什么? 当我们使用线程的时候,效率最高的方式当然是异步,即各个线程同时运行,其间不相互依赖和等待。但当不同的线程都需要访问某个资源的时候,就需要同步机制...
  • 原子变量自增的实现 2018-01-06 20:32:07
    原子变量自增大致有两种方式;一种是基于CPU硬件支持,而另一种为软件层面自旋实现;两者各有各的优势;理论上说软件 层面的现实是最通用的,不过它也带来了一些棘手的问题比如每个线程都在高频率的执行原子自增...
  • C# 原子操作 Interlocked 2020-01-20 20:15:58
    前言 焦虑与恐惧,往往是是因为想要的太多,但行动却太少。将目标放低,并制定足以达到目标的计划,并付之于一步一个脚印的行动。当你确信你在前进的时候,...Interlocked 提供了方法来实现原子操作,对于多线程共享...
  • 下图中的原子变量类就是Atomic类中的一部分。 也就是说,atomic类首先是一个乐观锁,然后底层实现也是根据CAS操作和Volatile关键字实现的。 Atomic 在JDK1.5之后,JDK的(concurrent包)并发包里提供了一些类来支持...
  • 前言 在当今科技高速发展的时代,计算机的高速发展早已超越“摩尔定律”。在这个计算机相对廉价的时代,作为开发者操作的机器早已不是单核处理器了,...什么是“原子变量类”? 自JDK1.5开始提供了java.util.conc...
  • 多线程操作会带来不一致性,为了实现一直性。我们可以用关键字:synchronized同步对象或者volatile轻量级、内存可见性。 两个关键字使用对比: 1、synchronized比较重...java已经实现了很多原子操作类:在java.ut...
  • c# 原子读写锁 2018-11-03 00:12:53
    我个人是以原子锁方式实现,主要用于并发读,独占写,并以写优先。关于优先的设计,应该有几种策略,就是读优先还是写优先还是均衡。我以写优先的原因在于,如果此时存在有待写入的数据,那么认为之前的数据已经过时...
  • 多线程访问共享资源的时候需要对线程进行互斥同步操作,在C++中可以选择原子变量和C++11中的mutex互斥量对象来进行互斥操作,该文章简单对两种同步操作进行一个效率的比较。工具:VS2017环境:WINDOW7 8核CPU首先...
  • c#多线程修改全局变量 2019-02-02 14:28:12
    C#中,在多个Form的Load事件中对一个全局变量修改,有什么好建议? 我的程序有一个MainForm,一个ChildForm MainForm是主界面,程序运行之后根据情况弹出多个ChildForm,在ChildForm的load事件中,我需要对一个全局...
  • Reads and writes of the following data types are atomic: bool, char, byte, sbyte, short, ushort, uint, int, float, and reference types. Reads and writes of doubles isn't atomic.
  • 以下多线程对int型变量x的操作,哪几个不需要进行同步 A. x=y; B. x++; C. ++x; D. x=1;   从上一节对“同步”概念的介绍得知,同步是指多个线程对资源的访问保证一定的顺序。 以上四个操作都是对资源x的访问...
  • 原子变量AtomicInteger 2015-10-23 16:14:31
    AtomicInteger适用范围:类的成员变量,在多线程中,数据被共享的,多个线程操作这个变量,才使用。局部变量及一个方法中不需要
  • c#线程基础之原子操作 2008-06-20 13:57:00
    使用System.Threading.Interlocked类可以提高线程的安全性,具体资料参考msdn: ...一般情况下,在子线程内使用i++这样的方式访问全局变量的方式是不安全的做法。测试下面的代码,在test1中经过100次number++,...
  • 共享变量可见性、原子 2018-05-28 13:58:29
    可见性:多线程环境下,一个线程修改共享变量,能够及时被其他线程所感知共享变量:一个变量在多个线程的工作内存都存在副本,这个变量就是共享变量线程对共享变量的操作只能在自己的工作内存中进行,不能主内存中...
  • 首先,查书看了一下原子操作的概念,自己编了一程序试了一下,果然,在C#中除了int型的赋值支持原子操作,其他的应该都需要同步锁定。测试代码如下: using System;using System.Collections.Generic;using ...
1 2 3 4 5 ... 20
收藏数 9,237
精华内容 3,694