【python】 多线程、多进程
什么是多线程?
在操作系统上,所有的应用程序都是通过进程来运行的。当一个应用程序启动时,操作系统会为该应用程序创建一个或多个进程,并为这些进程分配必要的资源,如内存空间、文件句柄等,以协助应用程序的运行。
在进程内部,可以同时存在多个线程。这些线程共享同一进程的地址空间和其他资源(如文件描述符、已打开的网络连接等),但它们各自拥有独立的执行栈和程序计数器。因此,线程之间的通信和同步变得相对简单,因为它们可以直接访问和修改共享的数据结构。
线程是操作系统调度CPU的基本单位。这意味着操作系统在分配CPU时间片给不同的任务时,是以线程为单位进行的。由于线程之间的切换开销相对较小(因为它们共享同一进程的地址空间),多线程编程可以有效地提高系统的并发性和响应性。
但是,值得注意的是,虽然线程是CPU调度的基本单位,但进程在操作系统中仍然扮演着至关重要的角色。进程是系统资源分配的基本单位,每个进程都有独立的内存空间和系统资源集。因此,进程之间的隔离性更强,一个进程的崩溃通常不会影响其他进程的运行。
【解决问题】怎么可以同时大量处理多个任务?
【解决的办法】多线程(threading模块)、多进程 (multiprocessing模块)两种办法
多线程(threading模块)
【适用场景】I/0 密集型任务
多进程 (multiprocessing模块)
【背景】在Python中,multiprocessing
是一个支持并发的模块,它允许程序员充分利用多核处理器。与threading
模块不同,multiprocessing
通过创建进程而不是线程来并行执行代码,从而规避了Python全局解释器锁(GIL)的限制。GIL是Python的一个特性,它限制了同一时间只有一个线程可以执行Python字节码,这在一定程度上影响了多线程的性能,特别是在执行CPU密集型任务时。
【适用场景】CPU 密集型任务,因为每个进程都有自己的Python解释器和内存空间,会提高计算能力。但是在cpython 中 每个进程中的多个线程会共享同一个
【生命周期】
新建:新建一个线程对象
就绪:调用start方法后,线程对象等待运行,什么时候开始运行取决于调度
运行:线程处于运行状态
阻塞:处于运行状态的线程被堵塞,通俗理解是被卡柱了,可能是因为程序自身调用sleep方法阻塞线程运行,或调用了一个阻塞式I/O方法,被阻塞的进程会等待何时解除阻塞重新运行
死亡:线程执行完毕或者异常退出,线程对象被摧毁并释放内存
【问题1】怎么让线程从这main 主线程结束?
【解决】当主线程执行完其所有代码后,Python解释器并不会立即退出。它会等待所有非守护线程完成它们的任务。只有所有非守护线程都结束后,Python解释器才会退出。守护线程则不同,当主线程结束时,守护线程会立即被终止。
1 import threading 2 import time 3 4 def worker(): 5 """守护线程的工作函数""" 6 while True: 7 print("Worker thread is running...") 8 time.sleep(1) # 暂停一秒 9 10 if __name__ == "__main__": 11 # 创建一个守护线程 ,daemon=True 12 t = threading.Thread(target=worker, daemon=True) 13 t.start() 14 15 # 主线程休眠3秒以观察守护线程的行为 16 print("Main thread is running...") 17 time.sleep(3) 18 print("Main thread is exiting...") 19 20 # 当主线程退出时,守护线程t会立即被终止,因此你将不会看到"Worker thread is running..."的进一步输出
【问题2】多进程中共享资源怎么进行数据交互?
【解决】
【知识点】
multiprocessing.Queue()和queue.Queue()的区别
Queue.Queue是进程内非阻塞队列,用于进程内的各函数模块或线程间通信。
multiprocess.Queue是跨进程通信队列。但是不能用于multiprocessing.Pool多进程的通信。
multiprocessing.Manager
进程池multiprocessing.Pool()的多进程之间的通信要用multiprocessing.Manager().Queue()
一个multiprocessing.Manager对象会控制一个服务器进程,其他进程可以通过代理的方式来访问这个服务器进程。从而达到多进程间数据通信且安全。
Manager支持的类型有list,dict,Namespace,Lock,RLock,Semaphore,BoundedSemaphore,Condition,Event,Queue,Value和Array。
个人理解:Manager()是一个中转站,用于把一些不能垮进程的对象共享给多进程。个人认为其效率不会很高。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)