'''
# 把“天猫精灵”与“小爱”看作两个线程,让它们同步。
天猫精灵:小爱同学
小爱:在
天猫精灵:我们来对古诗吧
小爱:好啊
天猫精灵:我在长江头
小爱:君在长江尾
天猫精灵:日日思君不见君
小爱:共饮长江水
天猫精灵:此水几时休
小爱:此恨何时已
天猫精灵:只愿君心似我心
小爱:定不负相思意
'''
import threading
from threading import Lock

"""条件变量:用于复杂的线程间同步"""
class XiaoAi(threading.Thread):
    def __init__(self,lock):
        super().__init__(name="小爱")
        self.lock = lock

    def run(self):
        self.lock.acquire()
        print("{}: 在".format(self.name))
        self.lock.release()

class TianMao(threading.Thread):
    def __init__(self,lock):
        super().__init__(name="天猫精灵")
        self.lock = lock

    def run(self):
        self.lock.acquire()
        print("{}: 小爱同学".format(self.name))
        self.lock.release()

if __name__ == "__main__":
    lock = Lock()
    xiaoai = XiaoAi(lock)    # 需要传递lock
    tianmao = TianMao(lock)

    tianmao.start()  # 假设天猫先开口说话
    xiaoai.start()
天猫精灵: 小爱同学
小爱: 在
import threading
from threading import Lock

"""条件变量:用于复杂的线程间同步"""
class XiaoAi(threading.Thread):
    def __init__(self,lock):
        super().__init__(name="小爱")
        self.lock = lock

    def run(self):
        self.lock.acquire()
        print("{}: 在".format(self.name))
        self.lock.release()

        self.lock.acquire()
        print("{}: 好啊".format(self.name))
        self.lock.release()

class TianMao(threading.Thread):
    def __init__(self,lock):
        super().__init__(name="天猫精灵")
        self.lock = lock

    def run(self):
        self.lock.acquire()
        print("{}: 小爱同学".format(self.name))
        self.lock.release()

        self.lock.acquire()
        print("{}: 我们来对古诗吧".format(self.name))
        self.lock.release()

if __name__ == "__main__":
    lock = Lock()
    xiaoai = XiaoAi(lock)    # 需要传递lock
    tianmao = TianMao(lock)

    tianmao.start()  # 假设天猫先开口说话
    xiaoai.start()
天猫精灵: 小爱同学
天猫精灵: 我们来对古诗吧
小爱: 在
小爱: 好啊

发现,当说的话较多时,逻辑混乱。如何保证天猫说一句,马上切换到小爱?需要用到Condition

import threading
from threading import Condition

"""条件变量:用于复杂的线程间同步; 通过Condition实现协同读诗"""
class XiaoAi(threading.Thread):
    def __init__(self,cond):
        super().__init__(name="小爱")
        self.cond = cond

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

            self.cond.wait()
            print("{}: 好啊".format(self.name))
            self.cond.notify()

            self.cond.wait()
            print("{}: 君在长江尾".format(self.name))
            self.cond.notify()

            self.cond.wait()
            print("{}: 共饮长江水".format(self.name))
            self.cond.notify()

            self.cond.wait()
            print("{}: 此恨何时已".format(self.name))
            self.cond.notify()

            self.cond.wait()
            print("{}: 定不负相思意".format(self.name))
            self.cond.notify()

class TianMao(threading.Thread):
    def __init__(self,cond):
        super().__init__(name="天猫精灵")
        self.cond = cond

    def run(self):
        with self.cond:
            print("{}: 小爱同学".format(self.name))
            self.cond.notify()  # 说完之后通知小爱
            self.cond.wait()

            print("{}: 我们来对古诗吧".format(self.name))
            self.cond.notify()  # 说完之后通知小爱
            self.cond.wait()

            print("{}: 我在长江头".format(self.name))
            self.cond.notify()  # 说完之后通知小爱
            self.cond.wait()

            print("{}: 日日思君不见君".format(self.name))
            self.cond.notify()  # 说完之后通知小爱
            self.cond.wait()

            print("{}: 此水几时休".format(self.name))
            self.cond.notify()  # 说完之后通知小爱
            self.cond.wait()

            print("{}: 只愿君心似我心".format(self.name))
            self.cond.notify()  # 说完之后通知小爱
            self.cond.wait()

if __name__ == "__main__":
    cond = Condition()
    xiaoai = XiaoAi(cond)    # 需要传递cond
    tianmao = TianMao(cond)

    xiaoai.start()   # 必须小爱开始说话,对话才可继续
    tianmao.start()  # 假设天猫先开口说话,则会卡在第一句话之后,没有后续的对话
'''
执行顺序很重要
如果天猫先执行,执行完第一条语句后就notify,而此时小爱并没有执行,wait方法之后透过
notify才可唤醒,当天猫进入wait时,小爱也不会发notify去唤醒天猫的wait
'''
'''
在调用with之后,才可以调用wait/notify方法
如果不用with,也可以用self.cond.acquire(),self.cond.release(), 注意acquire/release成对出现
'''
'''
condition有两层锁,一层底层锁会在线程调用了wait方法之后释放
上面的锁,会在每次调用wait的时候分配一把,并放入到cond的等待队列中,等到notify方法唤醒
每个wait方法都要申请一把锁,只有通过notify方法才会释放这把锁。
'''
天猫精灵: 小爱同学
小爱: 在
天猫精灵: 我们来对古诗吧
小爱: 好啊
天猫精灵: 我在长江头
小爱: 君在长江尾
天猫精灵: 日日思君不见君
小爱: 共饮长江水
天猫精灵: 此水几时休
小爱: 此恨何时已
天猫精灵: 只愿君心似我心
小爱: 定不负相思意