Python3 基础:多线程与多进程
多线程与多进程基础
Python 中的并发编程主要通过threading模块实现多线程,以及通过multiprocessing模块实现多进程。两者的核心区别在于:线程共享进程内存空间,适合 I/O 密集型任务;进程拥有独立内存空间,适合 CPU 密集型任务,且能绕过 GIL(全局解释器锁)的限制。
importthreadingimportmultiprocessing# 创建一个线程t=threading.Thread(target=lambda:print("Hello from thread"))# 创建一个进程p=multiprocessing.Process(target=lambda:print("Hello from process"))线程的创建与启动
使用threading模块可以方便地创建和管理线程:
importthreadingimporttimedefworker(name):print(f"Thread{name}starting")time.sleep(1)print(f"Thread{name}finished")# 创建线程t1=threading.Thread(target=worker,args=("A",))t2=threading.Thread(target=worker,args=("B",))# 启动线程t1.start()t2.start()# 等待线程完成t1.join()t2.join()print("All threads completed")常用线程同步机制
threading模块提供了丰富的线程同步工具:
importthreadingimporttime# 共享资源counter=0lock=threading.Lock()defincrement():globalcounterfor_inrange(1000):# 获取锁,防止竞态条件withlock:temp=counter time.sleep(0.0001)# 模拟操作延迟counter=temp+1# 创建多个线程threads=[]foriinrange(5):t=threading.Thread(target=increment)threads.append(t)t.start()# 等待所有线程完成fortinthreads:t.join()print(f"Final counter value:{counter}")线程池与并发执行
使用concurrent.futures模块可以更高效地管理线程池:
importconcurrent.futuresimporttimedeffetch_data(url):time.sleep(1)# 模拟网络请求returnf"Data from{url}"urls=["https://api.example.com/1","https://api.example.com/2","https://api.example.com/3"]# 使用线程池并发执行 I/O 密集型任务withconcurrent.futures.ThreadPoolExecutor(max_workers=3)asexecutor:results=executor.map(fetch_data,urls)forresultinresults:print(result)多进程的创建与管理
multiprocessing模块提供了与threading类似的 API,但运行在独立的进程中:
importmultiprocessingimportosdefcpu_intensive_task(n):pid=os.getpid()print(f"Process{pid}processing{n}")# 模拟 CPU 密集型计算total=0foriinrange(n):total+=i**2returntotalif__name__=="__main__":# 创建进程池withmultiprocessing.Pool(processes=4)aspool:numbers=[1000000,2000000,3000000,4000000]results=pool.map(cpu_intensive_task,numbers)print(f"Results:{results}")进程间通信
进程拥有独立内存空间,需要使用特定机制进行数据交换:
importmultiprocessingdefproducer(queue):foritemin["apple","orange","banana"]:queue.put(item)print(f"Produced:{item}")queue.put(None)# 发送结束信号defconsumer(queue):whileTrue:item=queue.get()ifitemisNone:breakprint(f"Consumed:{item}")if__name__=="__main__":# 创建队列用于进程间通信q=multiprocessing.Queue()p1=multiprocessing.Process(target=producer,args=(q,))p2=multiprocessing.Process(target=consumer,args=(q,))p1.start()p2.start()p1.join()p2.join()安全的数据共享
为防止数据竞争,推荐使用进程安全的同步原语:
importmultiprocessingdefincrement(shared_counter,lock):for_inrange(1000):# 获取锁,确保原子操作withlock:shared_counter.value+=1if__name__=="__main__":# 共享变量和锁counter=multiprocessing.Value('i',0)lock=multiprocessing.Lock()processes=[]for_inrange(5):p=multiprocessing.Process(target=increment,args=(counter,lock))processes.append(p)p.start()forpinprocesses:p.join()print(f"Final counter value:{counter.value}")自定义线程/进程类
通过继承基类可以实现更灵活的并发控制:
importthreadingclassCustomThread(threading.Thread):def__init__(self,name):super().__init__()self.name=namedefrun(self):print(f"Custom thread{self.name}is running")# 执行自定义任务result=sum(range(1000))print(f"Custom thread{self.name}finished with result:{result}")# 创建并启动自定义线程t=CustomThread("Worker-1")t.start()t.join()性能注意事项
并发编程在 Python 中需要特别注意性能和资源问题:
- I/O 密集型任务(网络请求、文件读写):优先使用多线程或
asyncio - CPU 密集型任务(计算、数据处理):优先使用多进程绕过 GIL
- 避免创建过多线程/进程,通常数量与 CPU 核心数相当或略多
- 注意线程安全和进程间通信的开销
- 考虑使用
concurrent.futures简化并发代码的管理
以上代码示例涵盖了 Python3 多线程与多进程的主要概念和操作,从基础用法到高级技巧,为开发者提供了全面的参考。
