python多线程同步有意义么_Python多线程同步

我认为您缺少了Condition的要点:必须检查condition对象内部的条件谓词/变量,而不是外部。在

condition.wait()的while点是它将等待直到收到通知。而且它会很便宜地等待,不使用CPU电源,也不会烧掉你的电池;在接到通知之前,它完全不会做任何事情。因此,如果您正确地使用它们,它们会按照您的要求执行:“仅当来自后台线程的do_something()未完成时,才等待后台线程。”

但你必须正确使用它们。在主线程上:with condition:

condition.wait_for(is_flag_set)

do_stuff()

然后,在后台线程上,您可以这样通知它:

^{pr2}$

为了简单起见,我取消了超时。如果要确保它等待到后台线程do_something(),或2分钟,以较早者为准:with condition:

if condition.wait_for(is_flag_set, 120):

do_stuff_after_flag_set()

else:

do_stuff_after_timeout()

现在,您可以保证,要么do_stuff_after_flag_set在后台线程上完成do_something之后才被调用,要么{}因为后台线程花费太长时间而被调用。在

如果您想了解(已编辑)现有代码的问题:if not is_flag_set():

with condition:

condition.wait(120)

您担心主线程会在条件设置之前检查标志。当然可以;在处理条件之前,可以先使用if。这就是为什么您必须使用wait_for,或者在wait周围使用while循环,就像在{a1}中一样;这是确保在通知您可以检查标志时检查它的唯一方法。在

另外,请注意,这里没有真正同步任何东西。如果对is_flag_set和set_flag的调用没有在with condition:内发生,则该标志不会在线程之间同步。(对于大多数平台上的CPython,您几乎总能逃脱惩罚,但如果您在寻找几乎总是可以逃脱惩罚的东西,而不是正确的,那么首先您确实不需要Condition)…)

注意事项:如果没有python3.2或更高版本,那么只有wait,而不是{},而且无法判断等待成功还是超时。除了超时问题,c.wait_for(is_flag_set)与while not is_flag_set(): c.wait()基本相同。所以您可以自己构建wait_for(注意,docs链接到source),或者可以在PyPI上找到一个后端口。

如果你想知道为什么你需要这样做,Wikipedia的Monitor文章很好地解释了这种额外复杂性所解决的问题。(如果您已经考虑了所有的竞争条件,并且知道您不需要Condition,请改用Event。)

请注意,我使用的是notify,而不是notify_all(或notifyAll,这是{}的另一个名称,但从python2.6开始就被弃用了)。如果只有一个服务员,你只需要通知一个服务员;这样做更简单,也更清楚你的意图。(如果有人看到notify_all,他们很可能会假设您使用的是线程池,而您并不是。)

还请注意,我将do_stuff()放在锁内。这实际上并不重要,除非您要重置标志并稍后再设置它。但如果是这样的话,这会保护你免受“错过周期”的错误。

最后,您需要一个wait_for或围绕wait的循环并不是真的;如果标志在整个程序中只被分配一次,并且条件只被通知一次,那么wait后面的if而不是之前的wait将具有相同的效果。(同样,使用Event或其他更简单的同步对象也是如此。)但是最好是安全地进行;这样,当您以后编辑看起来不相关的内容时,您不会意外地添加争用或死锁…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值