C#3.0核心技术-第19章线程-全新翻译注释-19.9(6)

19.9.5 仿真等待句柄

你也许已经注意到在前面的例子中有这样一个模式:两个等待循环都有下列结构:

clip_image001

flag在另一个线程中设置为true。这实际上是模仿一个AutoResetEvent。如果我们忽略flag=false,我们得到了一个ManualResetEvent;如果我们用一个整数字段替换标志,我们得到一个Semaphore。

在大多数情况下,仿真跨越一系列等待句柄工作的静态方法是容易的。调用WaitAll(其能够跨越一些事件等待句柄)的等价物只不过是一个用来代替等待句柄的结合所有标志的阻塞条件:

clip_image002

如果WaitAll由于COM遗留的问题经常不可用,这就特别有用。仿真WaitAny就是用||操作符替代&&操作符这样一件简单的事情。

SignalAndWait更有技巧。回忆这个方法在一个原子操作中向一个句柄发信号的同时在另一个句柄上等待。我们有了一个类似于分布式数据库事务的情况:我们需要一个两阶段提交!假定我们想要向flagA发出信号的同时在flagB上等待,我们就不得不将每个标志分成两个(译者注:即将flagA分成flagAphase1和flagAphase2,将flagB分成flagBphase1和flagBphase2),导致了看起来像下面一样的代码:

clip_image003

如果第一个Wait语句作为被中断或者被中止的结果抛出了一个异常,额外的“回滚”逻辑就会撤回flagAphase1(译者注:这里的意思就SignalAndWait模仿数据库事务的两段式提交:先用flagAphase1测试一下,如果成功则继续用flagAphase2完成真正的功能;如果失败,则回滚。这样就可以保证发信号和等待两件事情要么同时成功,要么同时失败。额外的回滚逻辑可以以try-catch的形式将上面的语句包括进去,并在catch中提供回滚的操作)。这是一个等待句柄更容易一些的场合。然而,真正的原子化的发信号和等待(译者注:即指SignalAndWait)是一个罕有的需求。

(译者注:原文的这一段关于SignalAndWait的描述一方面把问题简单化了,因为分布式数据库事务还需要一个“事务协调器”来协调不同“资源管理器(在这里就是对SignalAndWait的单一的一次调用)”;另一方面又把问题复杂化了,因为实际上要确保单一SignalAndWait调用中,发信号和等待两件事情要么同时成功要么同时失败,一阶段提交就足够了,无需两阶段提交。好在原文在这里仅仅是一个比喻,因此无碍大观。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值