Python Threading疑问:无阻塞逻辑下Consumer为何先于Producer执行?
问题分析与解答
首先,你遇到的线程执行顺序、Consumer未处理全部元素的问题,核心原因有两个:操作系统的线程调度机制,以及Consumer遍历列表的逻辑缺陷。
1. 线程启动≠立即执行
你调用t.start()只是把线程加入操作系统的就绪队列,至于哪个线程先获得CPU时间片执行,完全由操作系统的调度器决定,和你启动线程的顺序无关。比如你先启动Producer线程,操作系统可能先让它跑几个循环,再切换到Consumer线程;也有可能反过来,让Consumer先跑(此时data为空,Consumer的循环直接结束,什么都不打印)。你当前的输出里Producer先输出0-3,只是调度器这次选择了先让Producer执行一段时间。
2. Consumer的遍历逻辑不监听新元素
你的Consumer线程里用for i in data遍历列表,这个循环会在开始执行时生成一个列表的迭代器,迭代器只会遍历当时列表中已有的元素。也就是说:
- 如果Producer先往data里加了0、1、2、3这四个元素,此时Consumer开始循环,就只会遍历这四个元素;
- 之后Producer再追加第4个元素时,Consumer的循环已经结束了,所以不会处理这个元素——这也是你输出里
producer 4在Consumer输出之后的原因。
3. 程序的核心问题:缺乏线程同步
因为没有任何同步机制(比如锁、条件变量),Producer和Consumer完全独立执行,会导致:
- Consumer可能在data为空时就开始遍历,什么都不输出;
- Consumer无法处理Producer在它开始遍历之后追加的新元素;
- 虽然Python列表的
append方法是线程安全的,但如果有更复杂的操作(比如弹出元素),会出现竞态条件。
改进后的示例代码
如果想让Consumer能依次处理Producer生成的所有元素,可以用threading.Condition实现标准的生产者-消费者同步:
import threading import datetime from colorama import Fore as colorify def main() -> None: data = [] condition = threading.Condition() threads = [ threading.Thread(target=producer, args=(data, 5, condition), daemon=True), threading.Thread(target=consumer, args=(data, 5, condition), daemon=True) ] [t.start() for t in threads] [t.join() for t in threads] print(f"{colorify.YELLOW}Execution completed") def producer(data: list, num: int, condition: threading.Condition) -> None: for i in range(num): _t = datetime.datetime.now() sqrt = i * i with condition: data.append([i, _t]) print(f"{colorify.BLUE} producer {i} {threading.get_ident()}") condition.notify() # 通知Consumer有新数据可用 def consumer(data: list, num: int, condition: threading.Condition) -> None: count = 0 while count < num: with condition: # 等待直到data中有新元素 while not data: condition.wait() item = data.pop(0) count += 1 number = item[0] _t = item[1] print(f"{colorify.RED} consumer {number} {threading.get_ident()}") if __name__ == "__main__": main()
这个改进版本的特点:
- 用
Condition实现线程间的同步通知,Producer生产数据后唤醒等待的Consumer; - Consumer会一直等待直到有数据可用,保证每个生产的元素都被消费;
- 避免了竞态条件,执行顺序更符合生产者-消费者的预期逻辑。
内容的提问来源于stack exchange,提问作者That Coder
相关产品推荐
相关产品推荐

