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

 更新时间:2013年05月14日 15:26:23   作者:  
本篇文章是对Interlocked进行了详细的分析介绍,需要的朋友参考下

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

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

       二:增加或减少该值。

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

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

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


基本原理和上面的一致。

相关文章

  • C# System.BadImageFormatException问题及解决

    C# System.BadImageFormatException问题及解决

    这篇文章主要介绍了C# System.BadImageFormatException问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • C#中的var关键字用法介绍

    C#中的var关键字用法介绍

    这篇文章介绍了C#中的var关键字用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • C#.Net ArrayList的使用方法

    C#.Net ArrayList的使用方法

    这篇文章主要介绍了C#.Net ArrayList的使用方法,使用动态数组的优点是可以根据用户需要,有效利用存储空间,需要的朋友可以参考下
    2015-10-10
  • C# log4net日志库的用法小结

    C# log4net日志库的用法小结

    log4net日志开源库是用来控制日志文件大小,日志文件个数,滚动式覆盖,自由控制日志打印等级,今天通过本文给大家介绍C# log4net日志库的用法小结,感兴趣的朋友一起看看吧
    2021-10-10
  • C#创建及访问网络硬盘的实现

    C#创建及访问网络硬盘的实现

    本文主要介绍了C#创建及访问网络硬盘的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Winform中Treeview实现按需加载的方法

    Winform中Treeview实现按需加载的方法

    这篇文章主要介绍了Winform中Treeview实现按需加载的方法,针对大数据量的情况下非常具有实用价值,需要的朋友可以参考下
    2014-10-10
  • c#中list.FindAll与for循环的性能对比总结

    c#中list.FindAll与for循环的性能对比总结

    这篇文章主要给大家总结介绍了关于c#中list.FindAll与for循环的性能,文中通过详细的示例代码给大家介绍了这两者之间的性能,对大家的学习或工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧。
    2017-10-10
  • C#实现俄罗斯方块

    C#实现俄罗斯方块

    这篇文章主要为大家详细介绍了C#实现俄罗斯方块小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • C#使用AngleSharp库解析html文档

    C#使用AngleSharp库解析html文档

    这篇文章介绍了C#使用AngleSharp库解析html文档的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • C# WPF中RadioButton控件的用法及应用场景

    C# WPF中RadioButton控件的用法及应用场景

    在WPF应用程序中,RadioButton控件是一种常用的用户界面元素,本文主要介绍了C# WPF中RadioButton控件的用法及应用场景,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03

最新评论