自由锁(InterLocked)

http://blog.sina.com.cn/s/blog_a8c00bbb01016gty.html



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

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

2.       增加或减少该值。

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

 

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

 

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

 

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

 

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

 

关键就在于Interlocked.CompareExchange 中,Jeffrey Richter把它叫做InterLocked Anything 模式。

下面我们使用Interlocked.CompareExchange 实现求最大值的原子操作。

 

             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一样,所以可以使用委托调用的方式进行封装。

 

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;
                }
 

private long _killThreadFlag = 0;
        /// <summary>
        /// 线程安全的ON-OFF表示
        /// </summary>
        protected bool KillThreadFlag
        {
            get
            {
                return (Interlocked.Read(ref _killThreadFlag) == 1);
            }
            set
            {
                if (value)
                {
                    Interlocked.Exchange(ref _killThreadFlag, 1);
                }
                else
                {
                    Interlocked.Exchange(ref _killThreadFlag, 0);
                }
            }
        }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值