time.sleep对多线程的影响及多进程无竞态条件的原因
多线程与多进程的输出差异解析
场景说明
1. 多线程初始表现
运行以下多线程代码时,多数情况下输出first\nsecond,偶尔会出现firstsecond:
from threading import Thread from multiprocessing import Process import time def f(name): print(name) if __name__ == '__main__': for _ in range(10): t1 = Thread(target=f, args=['first']) t2 = Thread(target=f, args=['second']) t1.start() t2.start() t1.join() t2.join() print()
当给函数f添加time.sleep(0.01)后,多数情况下会得到类似firstsecond\nsecondfirst的交错输出。
2. 多进程表现
若改用multiprocessing的Process实现:
t1 = Process(target=f, args=['first']) t2 = Process(target=f, args=['second'])
则始终输出first\nsecond。
问题解答
1. time.sleep(0.01)对多线程输出的影响
Python的print函数不是原子操作——它会先把内容写入缓冲区,再执行换行(默认带换行符)。初始场景里,print(name)执行速度极快,操作系统的线程调度器大多还没来得及切换线程,t1就已经完成了整个print流程,所以多数时候输出正常;只有偶尔调度器会在t1写完first但还没输出换行时切换到t2,才会出现firstsecond的情况。
添加time.sleep(0.01)后,线程执行到sleep时会主动释放CPU时间片,触发操作系统的线程调度。这大幅提升了两个线程交替执行的概率:要么t1打印完first就进入睡眠,调度器切换到t2执行打印;要么t2先被调度执行,最终就出现了交错的输出结果。
2. 多进程为何无竞态条件
多进程和多线程的核心区别是内存空间完全隔离:每个进程都拥有独立的地址空间,包括独立的标准输出缓冲区。
在多进程场景中,t1和t2是两个完全独立的进程,它们的print操作各自写入自己进程的输出缓冲区,最后由操作系统统一把各个进程的输出同步到终端。即便进程之间存在调度切换,每个进程的输出内容都不会混写到同一个缓冲区里,自然不会出现输出交织的竞态条件,所以始终能得到有序的输出。
内容的提问来源于stack exchange,提问作者h s
相关产品推荐
相关产品推荐

