C# Interlocked 类( 三 )


Visual Studio 自带的分析工具,查看线程使用率

C# Interlocked 类

文章插图
使用 Process Explorer 工具查看代码执行过程中上下文切换数
C# Interlocked 类

文章插图

C# Interlocked 类

文章插图
可以大概估计出,采用 lock(Monitor)同步自增方式,上下文切换 243
那么我们用同样的方式看下底层用 CAS 函数执行自增的开销
Visual Studio 自带的分析工具,查看线程使用率
C# Interlocked 类

文章插图
使用 Process Explorer 工具查看代码执行过程中上下文切换数
C# Interlocked 类

文章插图

C# Interlocked 类

文章插图
可以大概估计出,采用 CAS 自增方式,上下文切换 220
可见,不论使用什么技术手段,线程创建太多都会带来大量的线程上下文切换
这个应该是和测试的代码相关
两者比较大的区别在CPU的使用率上,因为 lock 方式会造成线程阻塞,因此不会所有的CPU核心同时参与运算,CPU在当前进程上使用率不会太高,但 cas 方式CPU在自己的时间分片内并没有被阻塞或重新调度,而是不停地执行比较替换的动作(其实这种场景算是无用功,不必要的负开销),造成CPU使用率非常高 。
【总结】简单来说,Interlocked 类提供的方法给我们带来了方便快捷操作字段的方式,比起使用锁同步的编程方式来说,要轻量不少,执行效率也大大提高 。但是该技术并非银弹,一定要考虑清楚使用的场景后再决定使用,比如服务器web应用下,多线程执行大量耗费CPU的运算,可能会严重影响应用吞吐量 。虽然表面看起来执行这个单一的任务效率高一些(代价是CPU全部扑在这个任务上,无法响应其他任务),其实在我们的测试中,总共执行了 10000000 次运算,这种场景应该是比较极端的,而且在web应用场景下,用 lock 的方式响应时间也没有达到不能容忍的程度,但是用 lock 的好处是cpu可以处理其他用户请求的任务,极大提高了吞吐量 。
我们建议在竞争较少的场景,或者不需要很高吞吐量的场景下(简单说是CPU时间不那么宝贵的场景下)我们可以用 Interlocked 类来保证操作的原子性,可以适当提升性能 。而在竞争非常激烈的场景下,一定不要用 Interlocked 来处理原子性操作,改用 lock 方式会好很多 。
【源码地址】https://github.com/sevenTiny/CodeArts/blob/master/CSharp/ConsoleAppNet60/InterlockedTest.cs
【C# Interlocked 类】

经验总结扩展阅读