编写高质量代码改善C#程序的157个建议——建议89:在并行方法体中谨慎使用锁
建议89:在并行方法体中谨慎使用锁
除了建议88所提到的场合,要谨慎使用并行的情况还包括:某些本身就需要同步运行的场合,或者需要较长时间锁定共享资源的场合。
在对整型数据进行同步操作时,可以使用静态类Interlocked的Add方法,这就极大地避免了由于进行原子操作长时间锁定某个共享资源所带来的同步性能损耗。回顾建议83中的例子。
static void Main(string[] args)
{
int[] nums = new int[] { , , , };
int total = ;
Parallel.For<int>(, nums.Length, () =>
{
return ;
}, (i, loopState, subtotal) =>
{
subtotal += nums[i];
return subtotal;
},
(x) => Interlocked.Add(ref total, x)
);
Console.WriteLine("total={0}", total);
Console.ReadKey();
}
理论上,针对total的加法操作,需要使用一个同步锁,否则就无法避免一次torn read(即两次mov操作所导致的字段内存地址边界对齐问题)。FCL通过提供Interlocked类型解决了这个问题。FCL用来解决简单类型的原子性操作还提供了volatile关键字。不过这些都不是本建议所要讨论的重点。FCL现有的原子性操作为我们同步整型数据的时候,带来了性能上的提高。但是,在其他一些场合,我们却不得不考虑因为同步锁带来的损耗。
来看一个例子:
static void Main(string[] args)
{
SampleClass sample = new SampleClass();
Parallel.For(, , (i) =>
{
sample.SimpleAdd();
});
Console.WriteLine(sample.SomeCount);
} class SampleClass
{
public long SomeCount { get; private set; } public void SimpleAdd()
{
SomeCount++;
}
}
这段代码的输出或许是:
8322580
显然,这与我们的期待输出10000000有很大的差距。为了保证输出正确,必须为并行中的方法体加锁(假设SampleClass是外部提供的API,无权进行源码修改在其内部加锁):
object syncObj = new object();
Parallel.For(, , (i) =>
{
lock (syncObj)
{
sample.SimpleAdd();
}
});
经过以上修改后,代码输出就正确了。但是,这段代码也带来了另外的问题。由于锁的存在,系统的开销也增加了,同步带来的线程上下文切换,使我们牺牲了CPU时间与空间性能。简单地说,就是这段代码还不如不用并行。在建议73中曾经提到过,锁其实就是让多线程变成单线程(因为同时只允许有一个线程访问资源)。所以,我们需要谨慎地对待并行方法中的同步问题。如果方法体的全部内容都需要同步运行,就完全不应该使用并行。
转自:《编写高质量代码改善C#程序的157个建议》陆敏技
编写高质量代码改善C#程序的157个建议——建议89:在并行方法体中谨慎使用锁的更多相关文章
- 编写高质量代码改善C#程序的157个建议[1-3]
原文:编写高质量代码改善C#程序的157个建议[1-3] 前言 本文主要来学习记录前三个建议. 建议1.正确操作字符串 建议2.使用默认转型方法 建议3.区别对待强制转换与as和is 其中有很多需要理 ...
- 读书--编写高质量代码 改善C#程序的157个建议
最近读了陆敏技写的一本书<<编写高质量代码 改善C#程序的157个建议>>书写的很好.我还看了他的博客http://www.cnblogs.com/luminji . 前面部 ...
- 编写高质量代码改善C#程序的157个建议——建议157:从写第一个界面开始,就进行自动化测试
建议157:从写第一个界面开始,就进行自动化测试 如果说单元测试是白盒测试,那么自动化测试就是黑盒测试.黑盒测试要求捕捉界面上的控件句柄,并对其进行编码,以达到模拟人工操作的目的.具体的自动化测试请学 ...
- 编写高质量代码改善C#程序的157个建议——建议156:利用特性为应用程序提供多个版本
建议156:利用特性为应用程序提供多个版本 基于如下理由,需要为应用程序提供多个版本: 应用程序有体验版和完整功能版. 应用程序在迭代过程中需要屏蔽一些不成熟的功能. 假设我们的应用程序共有两类功能: ...
- 编写高质量代码改善C#程序的157个建议——建议155:随生产代码一起提交单元测试代码
建议155:随生产代码一起提交单元测试代码 首先提出一个问题:我们害怕修改代码吗?是否曾经无数次面对乱糟糟的代码,下决心进行重构,然后在一个月后的某个周一,却收到来自测试版的报告:新的版本,没有之前的 ...
- 编写高质量代码改善C#程序的157个建议——建议154:不要过度设计,在敏捷中体会重构的乐趣
建议154:不要过度设计,在敏捷中体会重构的乐趣 有时候,我们不得不随时更改软件的设计: 如果项目是针对某个大型机构的,不同级别的软件使用者,会提出不同的需求,或者随着关键岗位人员的更替,需求也会随个 ...
- 编写高质量代码改善C#程序的157个建议——建议153:若抛出异常,则必须要注释
建议153:若抛出异常,则必须要注释 有一种必须加注释的场景,即使异常.如果API抛出异常,则必须给出注释.调用者必须通过注释才能知道如何处理那些专有的异常.通常,即便良好的命名也不可能告诉我们方法会 ...
- 编写高质量代码改善C#程序的157个建议——建议152:最少,甚至是不要注释
建议152:最少,甚至是不要注释 以往,我们在代码中不写上几行注释,就会被认为是钟不负责任的态度.现在,这种观点正在改变.试想,如果我们所有的命名全部采用有意义的单词或词组,注释还有多少存在的价值. ...
- 编写高质量代码改善C#程序的157个建议——建议151:使用事件访问器替换公开的事件成员变量
建议151:使用事件访问器替换公开的事件成员变量 事件访问器包含两部分内容:添加访问器和删除访问器.如果涉及公开的事件字段,应该始终使用事件访问器.代码如下所示: class SampleClass ...
- 编写高质量代码改善C#程序的157个建议——建议150:使用匿名方法、Lambda表达式代替方法
建议150:使用匿名方法.Lambda表达式代替方法 方法体如果过小(如小于3行),专门为此定义一个方法就会显得过于繁琐.比如: static void SampeMethod() { List< ...
随机推荐
- Windbg查看w3wp进程占用的内存及.NET内存泄露,死锁分析
https://www.cnblogs.com/startpoint/p/4194052.html https://www.cnblogs.com/lyl6796910/p/7613664.html ...
- oracle打补丁步骤简介
1.了解opatchopatch是用于维护"个别"补丁的,有人称其为interim path或是one-off patch该命令的存放位置在$ORACLE_HOME下的OPatch ...
- Linux 服务器--Iptables 端口转发
日常Iptables 端口转发 需求:公司是局域网络,通过一个外网ip,进行互联网的访问.公司的云平台服务器在公网中,虚拟化平台中有一台内部服务器,用于公司某部门的使用,上面运行www 服务,ssh端 ...
- python‘s third day for me 字符串方法
基 础 数 据 类 型 初 始 int 运算.+ - * / ** %... bool: 判断,真假,作为条件. str: 存储少量的数据.操作简单,便于传输. list: 列表[ ...
- Shift Operations on C
The C standard doesn't precisely define which type of right shift should be used. For unsigned data, ...
- sql developer Oracle 数据库 用户对象下表及表结构的导入导出
Oracle数据库表数据及结构的导入导出 导出的主机与即将导入到的目标主机的tablespace 及用户名需一直!!!!!
- Python学习日记(一)——IDLE、运算符
环境:win8.1+python2.7.8 一.名词解释: 1.IDLE:经常编程的同学相信对集成开发环境(Integrated Development Environment,IDE)应该非常熟悉了 ...
- 3DMAX导出FBX的烘焙动画选项
勾选了 [烘焙动画]选项时,表示由骨骼动画塌陷为逐帧动画,这样的结果就是:导出的动画确保是正确的,但体积增大,这是骨骼动画与逐帧去画的区别所在. 如果不勾选此选项,则导出的是骨骼动画,可能出现一些问题 ...
- 关于Excel无法打开,因为文件格式或文件扩展名无效的解决方法
可能有网友也遇到过跟我一样的情况,新建的excel一打开就弹出 这样的错误. 这是因为excel打开的时候会去指定的文件夹找一个模板,以这个模板的样式打开新建的ecxel.所以如果excel打开的时候 ...
- onload函数和自执行函数的区别(jquery API网址:http://jquery.cuishifeng.cn/)
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...