python系列——多线程之条件变量condition
发布日期:2021-09-30 09:33:40 浏览次数:5 分类:技术文章

本文共 2278 字,大约阅读时间需要 7 分钟。

参考博客:

   (存钱取钱)

  (用于生产者消费者)

  (捉迷藏例子详细解释了condition的作用过程)

为什么要用condition:

当线程在系统中运行时,线程的调度具有一定的透明性,通常程序无法准确控制线程的轮换执行,如果有需要, 可通过线程通信来保证线程协调运行。

如何起作用:

假设系统中有两个线程,这两个线程分别代表存款者和取钱者,现在假设系统有一种特殊的要求,即要求存款者和取钱者不断地重复存款、取钱的动作,而且要求每当存款者将钱存入指定账户后,取钱者就立即取出该笔钱。不允许存款者连续两次存钱,也不允许取钱者连续两次取钱。

为了实现这种功能,可以借助于 Condition 对象来保持协调。使用 Condition 可以让那些己经得到 Lock 对象却无法继续执行的线程释放 Lock 对象,Condition 对象也可以唤醒其他处于等待状态的线程。

wait和release的区别:

release和wait都有释放锁的作用,不同在于wait后,该子线程就在那里挂起等待,要继续执行,就需要接收到notify或者notifyAll来唤醒线程,而release该线程还能继续执行。

wait会释放锁但是会挂起线程,不会继续向下运行。而release释放锁后有可能该线程继续向下运行。

阻塞和挂起的区别:

在说Condition之前还需要明确一下线程的几个概念。线程的阻塞和挂起,线程的这两个状态乍一看都是线程暂停不再继续往前运行,但是引起的原因不太一样。阻塞是指线程间互相的制约,当一个线程获得了锁,其他的线程就被阻塞了,而挂起是出于统一调度的考虑。换句话说,挂起是一种主动的行为,在程序中我们主动挂起某个线程然后可以主动放下让线程继续运行;而阻塞更多时候是被动发生的,当有线程操作冲突了那么必然是有一方要被阻塞的。从层级上看,挂起操作是高于阻塞的,也就说一个线程可以在阻塞的时候被挂起,然后被唤醒后依然是阻塞状态。如果在挂起过程中具备了运行条件(即不再阻塞),线程也不会往前运行。

捉迷藏具体例子:

import threading,timeclass Seeker(threading.Thread):    def __init__(self,cond,name):        Thread.__init__(self)        self.cond = cond        self.name = name    def run(self):        time.sleep(1)    #1.确保seeker晚于hider开始执行        self.cond.acquire()    #4. hider的锁释放了所以这里获得了锁        print '我把眼睛蒙上了'        self.cond.notify()    #5.蒙上眼后通知hider,hider线程此时被唤醒并试图获取锁,但是锁还在seeker身上,所以hider被阻塞,seeker继续往下        self.cond.wait()  #6. seeker锁被释放并且挂起,hider就获取锁开始继续往下运行了                print '我找到你了'        self.cond.notify()  #9.找到了之后通知hider,hider意图获取锁但不行所以被阻塞,seeker往下        self.cond.release()  #10.释放锁        print '我赢了'class Hider(threading.Thread):        def __init__(self,cond,name):            Thread.__init__(self)            self.cond = cond            self.name = name                def run(self):            self.cond.acquire()    #2.hider获取锁            self.cond.wait()    #3.hider被挂起然后释放锁                        print '我已经藏好了'            self.cond.notify()  #7.藏好后通知seeker,seeker意图获取锁,但是锁在hider身上所以seeker被阻塞            self.cond.wait()    #8.hider被挂起,释放锁,seeker获取锁,seeker继续往下运行            self.cond.release()  #11. 在此句之前一点,seeker释放了锁(#10),hider得到锁,随即这句hider释放锁            print '被你找到了'cond = threading.Condition()seeker = Seeker(cond,'seeker')hider = Hider(cond,'hider')seeker.start()hider.start()'''结果:我把眼睛蒙上了我已经藏好了我找到你了我赢了被你找到了'''

这里需要注意的是#10 self.cond.release方法不能省,否则会引起死锁。而#11 处的

self.cond.release() 可以被省略

转载地址:https://blog.csdn.net/h_jlwg6688/article/details/108461548 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:python系列——多线程之queue及线程池
下一篇:python新发现——打印有颜色的输出

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2024年03月30日 08时41分05秒