2026/2/21 23:57:38
网站建设
项目流程
北京建站模板展示,wordpress adroid,wordpress后台不见,企业公众号如何开通Python 多线程详解
1. 多线程的概念
在 Python 中#xff0c;多线程是指在一个进程内同时运行多个线程#xff0c;以便在某些场景下提升程序的响应能力或并发性。
线程是 CPU 调度的最小单位#xff0c;而进程是系统资源分配的最小单位。一个进程可以包含多个线程#xff0…Python 多线程详解1. 多线程的概念在 Python 中多线程是指在一个进程内同时运行多个线程以便在某些场景下提升程序的响应能力或并发性。线程是 CPU 调度的最小单位而进程是系统资源分配的最小单位。一个进程可以包含多个线程这些线程共享同一进程的资源包括内存空间。⚠注意Python 的GILGlobal Interpreter Lock全局解释器锁限制了同一时刻只能有一个线程执行Python 字节码所以多线程在计算密集型任务中无法真正实现并行更多用于I/O 密集型任务例如网络请求、文件读写。2. 多线程的初始化在 Python 中可以使用threading模块来创建和管理线程。2.1 使用threading.Threadimportthreadingimporttimedefworker(name):print(f线程{name}开始工作)time.sleep(1)print(f线程{name}工作结束)# 创建线程对象t1threading.Thread(targetworker,args(A,))t2threading.Thread(targetworker,args(B,))# 启动线程t1.start()t2.start()# 等待线程结束t1.join()t2.join()print(所有线程执行完毕)关键参数target线程运行的函数。args传给函数的参数元组形式。kwargs传给函数的关键字参数。3. 线程之间的变量传递3.1 共享变量线程之间可以共享同一个全局变量因为它们在同一个进程中但这会引发数据竞争问题。importthreading counter0# 全局变量defincrement():globalcounterfor_inrange(100000):counter1# 多线程这里可能会出错threads[]for_inrange(5):tthreading.Thread(targetincrement)threads.append(t)t.start()fortinthreads:t.join()print(counter ,counter)上面的代码可能不会得到想象的结果因为多个线程同时修改counter会产生竞态条件。4. 线程锁Lock为避免数据竞争我们需要使用锁Lock来确保某段代码同一时刻只有一个线程能执行。importthreading counter0lockthreading.Lock()defsafe_increment():globalcounterfor_inrange(100000):withlock:# 自动 acquire/releasecounter1threads[]for_inrange(5):tthreading.Thread(targetsafe_increment)threads.append(t)t.start()fortinthreads:t.join()print(counter ,counter)# 结果正确4.1Lock的用法lockthreading.Lock()# 方式1lock.acquire()try:# 临界区代码passfinally:lock.release()# 方式2 (推荐)withlock:# 临界区代码pass5. 线程间通信除了共享变量还可以使用队列Queue来安全地进行线程间数据传递。importthreadingimportqueueimporttime qqueue.Queue()defproducer():foriinrange(5):q.put(i)print(f生产数据{i})time.sleep(0.2)defconsumer():whileTrue:itemq.get()ifitemisNone:# 遇到 None 退出breakprint(f消费数据{item})time.sleep(0.3)q.task_done()t1threading.Thread(targetproducer)t2threading.Thread(targetconsumer)t1.start()t2.start()t1.join()q.put(None)# 通知消费者退出t2.join()优点queue.Queue()是线程安全的内部已经做好了加锁处理无需手动使用 Lock。6. 守护线程Daemon Thread守护线程会在主线程结束时自动退出。tthreading.Thread(targetworker)t.daemonTrue# 设为守护线程t.start()适合做后台任务例如日志记录或心跳检测。7. 线程池ThreadPoolExecutor如果需要频繁创建和销毁线程可以使用线程池来提升性能。fromconcurrent.futuresimportThreadPoolExecutordeftask(name):print(f{name}开始)returnf{name}完成withThreadPoolExecutor(max_workers3)asexecutor:futures[executor.submit(task,f任务{i})foriinrange(5)]forfutureinfutures:print(future.result())8. 总结与建议计算密集型任务推荐使用多进程multiprocessing而不是多线程避免 GIL 限制。I/O 密集型任务推荐使用多线程或异步asyncio。使用Lock或Queue解决数据竞争和线程安全问题。合理规划线程数量不要盲目创建过多线程。可以用ThreadPoolExecutor简化线程管理。