Csharp/C#教程:深入多线程之:深入分析Interlocked分享

在大多数计算机上,增加变量操作不是一个原子操作,需要执行下列步骤:

      一:将实例变量中的值加载到寄存器中。

      二:增加或减少该值。

      三:在实例变量中存储该值。

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

Interlocked可以为多个线程共享的变量提供原子操作。

   Interlocked.Increment:以原子操作的形式递增指定变量的值并存储结果。
   Interlocked.Decrement以原子操作的形式递减指定变量的值并存储结果。
   Interlocked.Add以原子操作的形式,添加两个整数并用两者的和替换第一个整数

但是Interlocked并没有为乘法,除法提供原子操作。那么如何实现乘法,除法,以及为其他的一些非原子操作提供原子操作的支持呢??

关键就在于Interlocked.CompareExchange中,JeffreyRichter把它叫做InterLockedAnything模式。

下面我们使用Interlocked.CompareExchange实现求最大值的原子操作。
代码如下:
publicstaticintMaximum(refinttarget,intvalue)
       {
           intcurrentVal=target;  //将target的当前值保存到currentVal中
           intstartVal,desiredVal; //声明两个变量来记录操作开始前的值和期望的结果值。

           do
           {
               startVal=currentVal;//将currentVal中的值保存到startVal中,此时记录的是target在操作开始前的最初值。
               desiredVal=Math.Max(startVal,value);//通过startVal进行复杂的计算,返回一个期望的结果,在这里仅仅是返回两者的最大值。

               //线程可能在这里被抢占,target的值可能被改变
               //如果target的值被改变了,那么target和startVal的值就不想等,所以就不应该用desiredVal替换target.
               //如果target的值没有被改变,那么target和startVal的值就像等,使用desiredVal替换target.
               //不管替换或者不替换,CompareExchange的返回值始终是target的值,所以currentVal的值现在是target的最新值。

               //CompareExchange:将target和startVal的值比较,相等则用desiredVal替换,否则不操作,
               //不管替换还是不替换返回的都是原来保存在target的值。
               currentVal=Interlocked.CompareExchange(reftarget,desiredVal,startVal);
           }while(startVal!=currentVal);//当target的起始值和最新值不相等的时候,说明target被修改了,所以继续下次判断,否则退出循环。
           returndesiredVal;
       }

这段代码的核心就是:currentVal=Interlocked.CompareExchange(reftarget,desiredVal,startVal);
//将target的值和startVal的值比较,相等则用desiredVal替换target,否则不操作,
//不管替换还是不替换返回的都是原来保存在target的值。

在这里,计算可能会比较复杂,而不像上面的Math.Max一样,所以可以使用委托调用的方式进行封装。
代码如下:
delegateintMorpher<TResult,TArgument>(intstartValue,TArgumentargument,
           outTResultmorphResult);

       staticTResultMorph<TResult,TArgument>(refinttarget,TArgumentargument,
           Morpher<TResult,TArgument>morpher)
       {
           TResultmorphResult;

           intcurrentVal=target,startVal,desiredVal;

           do
           {
               startVal=currentVal;
               desiredVal=morpher(startVal,argument,outmorphResult);
               currentVal=Interlocked.CompareExchange(reftarget,desiredVal,startVal);
           }while(startVal!=currentVal);

           returnmorphResult;
       }

基本原理和上面的一致。

您可能感兴趣的文章:.NET中保证线程安全的高级方法Interlocked类使用介绍C#中使用Interlocked进行原子操作的技巧

标签: 线程 多线程 rl ed 程之 oc te

C++实现二叉树非递归遍历方法实例上述就是C#学习教程:深入多线程之:深入分析Interlocked分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/904728.html

(0)
上一篇 2021年10月22日
下一篇 2021年10月22日

精彩推荐