- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
CPU的同步机制
同步机制漫谈
张银奎 yinkui.zhang@
更快是计算机世界的一个永恒主题。要做到更快有两个方向:一是提高串行执行的速度,二是并行计算(Parallel Computing)。并行计算又可分为同一CPU内部多个流水线间的并行、同一个系统内多个CPU间的并行、和同一个网络中多个计算机系统间的并行。
当并行运行的多个任务彼此无关,互不依赖时,整个系统的性能是最高的。但在现实的并行计算中,这是不可能的。至少同一组内的多个任务之间是存在依赖关系的,它们需要交流信息,报告彼此的计算结果;调整进度,确保各个任务都有条不紊的进行;协调资源,确保共享数据的一致性和安全性和最终结果的正确性。这样便产生了并行计算中的一个基本问题,那就是同步(Synchronization)。并行计算的特征决定了同步是它的一个必然问题。
为了易于理解,我们看一个从银行账户中存款和提款的简单例子,清单1给出的是账户类CAccount的Withdraw和Deposit方法的C++代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 BOOL CAccount::Withdraw(double dblNumber)
{
BOOL bRet=TRUE;
if(GetBalance()=dblNumber)
{
// Send out money now, we use sleep to simulate
Sleep(rand());
m_dblBalance-=dblNumber;
}
else
{
bRet = FALSE;
}
Log(TASK_WITHDRAW,dblNumber,bRet);
return bRet;
}
void CAccount::Deposit(double dblNumber)
{
m_dblBalance+=dblNumber;
Log(TASK_DEPOSIT,dblNumber,TRUE);
} 以上方法很容易理解,参数dblNumber是要支出或存入的金额,第4行检查帐户余额是否足够本次提取,第7行执行支付操作,我们调用Sleep函数延迟一段时间来模拟这个操作,第8行修改账户余额。
图1是使用以上类的TaskSync程序的界面和一次执行记录。点击Deposit和Withdraw按钮会触发创建新的线程来调用CAccount类的Deposit和Withdraw 方法。编辑框中的数字既是存入和支出的金额,又是要创建的线程数,因为我们让每个线程都固定的存入或取出1元钱。
在编辑框中各输入10后,随机的反复点击Deposit和Withdraw按钮,持续一段时间后,我们会发现余额变成了负数。
图1 TaskSync程序
观察清单1中的代码,只有在确保余额不小于参数dblNumber时(第4行)才会执行取款动作,然后递减余额(m_dblBalance)。也就是说这个账户是不应该出现负数余额的(不可透支)。那么,是什么原因导致余额变为负数呢?以下是几种猜想:
在某个(些)线程执行取款动作的过程中(第7行),其它线程又修改了余额值。尽管第4行作判断时账户中还有足够的余额,但是在执行递减操作时,其它线程(提款机)可能已经把余额递减为0了,于是再次递减便出现了负数。
在某个(些)线程更新m_dblBalance变量时,也就是执行递减操作(第8行)时,其它线程又修改了它的值。清单2列出了m_dblBalance-=dblNumber语句所对应的汇编代码。可见尽管C++是一条语句,但是编译出的汇编语句还是有很多条的。第1行(清单2)是将this指针存入EAX寄存器,第2行是将m_dblBalance(this+8)从内存加载到FPU(符点处理单元)寄存器栈中,第3行是执行减法运算,ebp+8指向的是参数dblNumber,第4行是将this指针存入ECX寄存器,第5行是将计算结果存回内存中的m_dblBalance成员变量。因为第3行的减法计算是对加载在CPU寄存器中的值做减法,第5行再将这个值存回内存,那么如果在某个线程执行2、3条指令的间隙,其它线程修改了m_dblBalance,那么这个线程使用的仍然是旧的数据,而且第5行会将错误的结果写入到内存中。
在32位x86系统中,m_dblBalance变量在内存中的长度是8个字节(QWORD)。这意味着存取这个变量时需要读写8个字节。如果,两个线程恰好都要读写这8个字节,那么有可能某个线程读到的内容是另一个线程写了一半的数据,或者某个线程写了8个字节的前半部分,另一个线程写了后半部分。
清单2 m_dblBalance-=dblNumber语句所对应的汇编代码
1
2
3
4
5 00
原创力文档


文档评论(0)