python条件同步线程threading.Condition

时间:2022-05-16 17:41:56   收藏:0   阅读:6

condition类里内置了一把RLock锁,有acquire方法和release方法,还有wait,notify,notifyAll方法,

使用acquire方法可以获得RLock锁

使用wait方法就会放掉锁并处于阻塞状态,等其他线程中有使用notify方法时,在wait前的acquire方法处继续线程(注意:而不是紧随wait后面执行)。

notify会唤醒一个wait,但是不会立即跳转到另一个线程的wait处,必须在notify后使用release才能跳转到正在wait的线程的wait语句处。不然不释放锁,wait就继续不了,必须先确认肯定有一个wait时,才可以notify,否则会报错。

import threading
import time
import sys  # 方便调用sys.stdout.write方法取代print方法,因为print具有线程不安全性(换行符会有被拆分输出的机率)


condition = threading.Condition()
item = []  # 列表表示大盘子,最多可以放20个包子
item_id = 0  # 包子的号码


class Producer(threading.Thread):
    def __init__(self, name, n):
        threading.Thread.__init__(self, name=name, args=n)  # 需要先调用父类的构造函数
        self.name = name
        self.n = n  # 要做的包子数

    def run(self):
        global item, item_id
        while self.n != 0:  # 准备开始做一共做n个包子
            condition.acquire()  # 只在读取或改变公有变量/成员时获取线程锁
            if len(item) == 20:
                sys.stdout.write(f桌子放满了,{self.name}暂停做包子\n)
                condition.wait()
            item.append(item_id)  # 做好的包子放进盘子里
            item_id += 1  # 包子号递增
            sys.stdout.write(f"{self.name}做好了一个包子,放盘子里了{item}\n")
            if len(item) == 1:
                condition.notify()  # 如果盘里现在是1个包子,则通知顾客吃包子
            self.n -= 1  # 需要做的包子数递减
            condition.release()  # 改变公有变量/成员后立即释放锁,以减少线程阻塞时间
            time.sleep(3)  # 3秒钟做一个包子
        else:
            sys.stdout.write(f"{self.name}做包子任务完成了\n")


class Consumer(threading.Thread):
    def __init__(self, name, n):
        threading.Thread.__init__(self, name=name, args=n)  # 需要先调用父类的构造函数
        self.name = name
        self.n = n  # 要吃的包子数

    def run(self):
        global item
        while self.n != 0:
            condition.acquire()  # 只在读取或改变公有变量/成员时获取线程锁
            if len(item) == 0:
                sys.stdout.write(f{self.name}等待包子中\n)
                condition.wait()
            del item[0]  # 销毁先做好的包子
            sys.stdout.write(f{self.name}吃掉了一个包子{item}\n)
            if len(item) == 19:
                condition.notify()  # 如果现在盘子里有19个包子,则通知生产者可以继续生产了
            self.n -= 1
            condition.release()  # 改变公有变量/成员后立即释放锁,以减少线程阻塞时间
            time.sleep(1)  # 一秒钟吃一个包子
        else:
            sys.stdout.write(f{self.name}包子吃够了\n)


if __name__ == __main__:
    threads = []
    for i in range(1, 3):  # 先建立两个顾客
        threads.append(Consumer(C + str(i), 10))  # 每个顾客准备消费10个包子
    for i in range(1, 6):  # 再建立5个包子生产者
        threads.append(Producer(P+str(i), 4))  # 每个生产者各生产4个包子
    for t in threads:
        t.start()
    for t in threads:
        t.join()
    print("完毕")

 

原文:https://www.cnblogs.com/bohua320/p/15313351.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!