源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

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

  • 时间:2020-03-23 09:59 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:深入多线程之:深入分析Interlocked
在大多数计算机上,增加变量操作不是一个原子操作,[b]需要执行下列步骤:[/b]        一:将实例变量中的值加载到寄存器中。        二:增加或减少该值。        三:在实例变量中存储该值。 在多线程环境下,线程会在执行完前两个步骤后被抢先。然后由另一个线程执行所有三个步骤,当第一个线程重新开始执行时,它覆盖实例变量中的值,造成第二个线程执行增减操作的结果丢失。 [b]Interlocked可以为多个线程共享的变量提供原子操作。[/b]     Interlocked.Increment:以原子操作的形式递增指定变量的值并存储结果。     Interlocked.Decrement以原子操作的形式递减指定变量的值并存储结果。     Interlocked.Add以原子操作的形式,添加两个整数并用两者的和替换第一个整数 但是Interlocked并没有为乘法,除法提供原子操作。那么如何实现乘法,除法,以及为其他的一些非原子操作提供原子操作的支持呢?? 关键就在于Interlocked.CompareExchange 中,Jeffrey Richter把它叫做InterLocked Anything 模式。 下面我们使用Interlocked.CompareExchange 实现求最大值的原子操作。
[u]复制代码[/u] 代码如下:
public static int Maximum(ref int target, int value)         {             int currentVal = target;   //将target的当前值保存到currentVal中             int startVal, 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(ref target, desiredVal, startVal);             } while (startVal != currentVal); //当target的起始值和最新值不相等的时候,说明target被修改了,所以继续下次判断,否则退出循环。             return desiredVal;         }
这段代码的核心就是:currentVal = Interlocked.CompareExchange(ref target, desiredVal, startVal); // 将target的值和startVal的值比较,相等则用desiredVal替换target,否则不操作, //不管替换还是不替换返回的都是原来保存在target的值。 在这里,计算可能会比较复杂,而不像上面的Math.Max一样,所以可以使用委托调用的方式进行封装。
[u]复制代码[/u] 代码如下:
delegate int Morpher<TResult, TArgument>(int startValue, TArgument argument,             out TResult morphResult);         static TResult Morph<TResult, TArgument>(ref int target, TArgument argument,             Morpher<TResult, TArgument> morpher)         {             TResult morphResult;             int currentVal = target, startVal, desiredVal;             do             {                 startVal = currentVal;                 desiredVal = morpher(startVal, argument, out morphResult);                 currentVal = Interlocked.CompareExchange(ref target, desiredVal, startVal);             } while (startVal != currentVal);             return morphResult;         }
[b]基本原理和上面的一致。[/b]
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部