python中的wait和notify

上一篇只是大概的讲了一些怎么给数据加锁以及创建线程的两种方式。这次讲一下python中的wait和notify

现在假如有如下情况:

小明:小红

小红:在

小明:我喜欢你
小红:对不起,你是个好人。

对于这种一问一答的方式,我们是否也可以通过加锁来解决呢,我们看代码。

import threading

class XiaoMing(threading.Thread):
    def __init__(self,lock):
        super().__init__(name='小明')
    
    
    def run(self):
        lock.acquire()
        print('{}:小红'.format(self.name))
        lock.release()

        lock.acquire()
        print('{}:我喜欢你'.format(self.name))
        lock.release()

class XiaoHong(threading.Thread):
    def __init__(self,lock):
        super().__init__(name='小红')
    
    def run(self):
        lock.acquire()
        print('{}:在'.format(self.name))
        lock.release()

        lock.acquire()
        print('{}:对不起,你是个好人'.format(self.name))
        lock.release()

if __name__ == '__main__':
    lock = threading.Lock()
    xiaoming = XiaoMing(lock)
    xiaohong = XiaoHong(lock)
    
    xiaoming.start()
    xiaohong.start()

这个时候会出现一个现象,我们发现执行的结果是

小明:小红
小明:我喜欢你
小红:在
小红:对不起,你是个好人

很显然,这跟我们想要的结果是不一样的,那么为什么会导致这样的结果呢。

原因就在于我们在小明说完小红的时候会释放锁,接着小明这个线程又拿到了锁,这个时候又继续说了我喜欢你。这就是导致结果跟预期不一致的原因。

因此我们在这里引出了wait和notify这两个方法,这两个方法属于threading的Condition类,condition是一个条件变量,是用来控制复杂的线程之间的同步。

如果看过condition的源码,就会发现condition实现了__enter__ 和__exit__这两个魔术方法,因此我们可以通过with语句来使用condition这个变量。

再说一下wait和notify,wait()只有在被notify唤醒时,才会继续往下执行。因此会有下面这样的代码。

import threading
from threading import Condition


class XiaoMing(threading.Thread):
    def __init__(self,condition):
        super().__init__(name='小明')
        self.condition = condition
    
    def run(self):
        with self.condition:
            print('{}:小红'.format(self.name))
            self.condition.notify()
            self.condition.wait()

            print('{}:我喜欢你'.format(self.name))
            self.condition.notify()
            self.condition.wait()


class XiaoHong(threading.Thread):
    def __init__(self,condition):
        super().__init__(name='小红')
        self.condition = condition

    def run(self):
        with self.condition:
            self.condition.wait()
            print('{}:在'.format(self.name))
            self.condition.notify()

            self.condition.wait()
            print('{}:对不起,你是个好人'.format(self.name))
            self.condition.notify()

if __name__ == '__main__':
    condition = threading.Condition()
    xiaoming = XiaoMing(condition)
    xiaohong = XiaoHong(condition)
    
    xiaohong.start()
    xiaoming.start()

运行上面的代码,我们发现执行结果按照我们预期的进行了。需要注意的一点就是start的顺序改了,是小红先start,小明才start。

如果是小明先start的话,那么小红就会在小明notify之后才start,这样小红的wait就收不到小明发过来的信号了,因此会导致

程序一直卡住。

其实这个condition的源码里面,在初始化condition的时候,就会上一把锁,这样另一个线程就进不去with里面了,

而在调用wait的时候,会先把condition时初始化的锁释放掉,然后再分配一把锁到condition的等待队列中,等待notify的唤醒。

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值