Python两线程交替打印0-5奇偶数字异常问题排查与修正
线程交替打印异常A:6的原因分析与修复方案
问题原因
核心问题在于while循环的条件判断在锁之外:
- 当
i=5时,线程A通过while i <=5的判断进入循环,此时线程B抢先获取锁,处理i=5:打印B:5,将owner改为A,i自增为6,随后释放锁。 - 线程A拿到锁后,虽然
i已经是6,但因之前已通过循环判断,且此时owner为A,仍会执行打印逻辑,输出A:6,之后i变为7,下一次循环判断i<=5不成立才退出。
修复方案
方案一:锁内判断终止条件,避免无效执行
修改线程函数,将i的终止判断移到锁内部,确保只有当i<=5且当前线程拥有打印权限时才执行操作:
import threading lock = threading.Lock() owner = "A" i = 0 def test1(): global owner, i while True: lock.acquire() # 先判断是否已超出范围,是则直接退出 if i > 5: lock.release() break if owner == "A": print(f"{owner}:{i}") owner = "B" i += 1 lock.release() def test2(): global owner, i while True: lock.acquire() if i > 5: lock.release() break if owner == "B": print(f"{owner}:{i}") owner = "A" i += 1 lock.release() A = threading.Thread(target=test1) B = threading.Thread(target=test2) A.start() B.start() A.join() B.join()
方案二:使用Condition条件变量(更优雅,避免忙等)
原代码存在忙等问题(线程不断循环获取锁、判断、释放),使用threading.Condition可以让线程在条件不满足时进入等待状态,减少资源消耗:
import threading cond = threading.Condition() i = 0 def print_even(): global i while i <= 5: with cond: # 等待直到当前i为偶数 while i % 2 != 0: cond.wait() if i > 5: break print(f"A:{i}") i += 1 # 唤醒等待的奇数线程 cond.notify() def print_odd(): global i while i <= 5: with cond: # 等待直到当前i为奇数 while i % 2 == 0: cond.wait() if i > 5: break print(f"B:{i}") i += 1 # 唤醒等待的偶数线程 cond.notify() A = threading.Thread(target=print_even) B = threading.Thread(target=print_odd) A.start() B.start() A.join() B.join()
内容的提问来源于stack exchange,提问作者Super Kai - Kazuya Ito
相关产品推荐
相关产品推荐

