MST

星途 面试题库

面试题:Python多线程中条件变量(Condition)的应用场景及实现

描述在Python多线程中,`Condition`通常在哪些场景下使用?请举例说明如何使用`Condition`来实现线程间的复杂同步,例如生产者 - 消费者模型,写出关键代码片段并解释每一步的作用。
31.9万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

Condition的使用场景

  1. 线程间复杂同步:当线程间需要根据某些条件进行复杂的同步操作时使用,比如一个线程需要等待另一个线程完成特定任务后才能继续执行,而不仅仅是简单的锁机制能满足的场景。
  2. 生产者 - 消费者模型:生产者和消费者线程之间需要协调数据的生产和消费节奏,确保缓冲区不会溢出或空读。

生产者 - 消费者模型关键代码片段及解释

import threading
import time


class Producer(threading.Thread):
    def __init__(self, condition, buffer):
        threading.Thread.__init__(self)
        self.condition = condition
        self.buffer = buffer

    def run(self):
        for i in range(10):
            with self.condition:
                # 检查缓冲区是否已满
                while len(self.buffer) >= 5:
                    print("缓冲区已满,生产者等待")
                    self.condition.wait()
                self.buffer.append(i)
                print(f"生产者生产: {i}")
                # 通知消费者可以消费了
                self.condition.notify()
            time.sleep(1)


class Consumer(threading.Thread):
    def __init__(self, condition, buffer):
        threading.Thread.__init__(self)
        self.condition = condition
        self.buffer = buffer

    def run(self):
        while True:
            with self.condition:
                # 检查缓冲区是否为空
                while not self.buffer:
                    print("缓冲区为空,消费者等待")
                    self.condition.wait()
                item = self.buffer.pop(0)
                print(f"消费者消费: {item}")
                # 通知生产者可以生产了
                self.condition.notify()
            time.sleep(1)


if __name__ == "__main__":
    buffer = []
    condition = threading.Condition()
    producer = Producer(condition, buffer)
    consumer = Consumer(condition, buffer)

    producer.start()
    consumer.start()

    producer.join()
    consumer.join()
  1. 初始化部分
    • 定义了ProducerConsumer两个类,继承自threading.Thread
    • 每个类的构造函数接收conditionbuffercondition用于线程间同步,buffer作为共享的数据缓冲区。
  2. 生产者Producer
    • run方法是线程执行体。
    • 使用with self.condition语句获取锁,进入临界区。
    • while len(self.buffer) >= 5:循环检查缓冲区是否已满,如果满了,调用self.condition.wait()释放锁并等待,直到被其他线程唤醒。
    • 当缓冲区不满时,生产数据并添加到缓冲区,打印生产信息。
    • 调用self.condition.notify()通知等待在condition上的其他线程(通常是消费者线程)。
  3. 消费者Consumer
    • run方法为线程执行体。
    • 同样使用with self.condition获取锁进入临界区。
    • while not self.buffer:循环检查缓冲区是否为空,如果空了,调用self.condition.wait()释放锁并等待,直到被唤醒。
    • 当缓冲区有数据时,从缓冲区取出数据,打印消费信息。
    • 调用self.condition.notify()通知等待在condition上的其他线程(通常是生产者线程)。
  4. 主程序部分
    • 创建共享缓冲区bufferCondition对象condition
    • 实例化生产者和消费者线程,并启动它们。
    • 调用join方法等待两个线程执行完毕。