【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()是一个中转站,用于把一些不能垮进程的对象共享给多进程。个人认为其效率不会很高。

posted on   张凌赫_帅  阅读(8)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示