Python的秘密基地--[章节15] Python 多线程与并发编程
第15章:Python 多线程与并发编程
在现代计算中,提高程序性能的关键之一是并发编程。Python 提供了多线程、多进程和异步编程等多种方式来提高程序的执行效率。本章将介绍 Python 的 threading、multiprocessing 以及 asyncio 库,帮助你掌握并发编程的核心概念和实战技巧。
15.1 并发与并行的区别
- 并发(Concurrency):任务之间交替执行,提高程序的响应速度。例如,一个 Web 服务器可以同时处理多个请求,但可能只有一个 CPU 核心在执行。
- 并行(Parallelism):多个任务同时运行,通常需要多核 CPU 支持。例如,大型计算任务可以拆分成多个小任务并行计算。
Python 提供三种并发编程方式:
- 多线程(threading) - 适用于 I/O 密集型任务,如网络请求、文件读写。
- 多进程(multiprocessing) - 适用于 CPU 密集型任务,如数据分析、数学计算。
- 异步编程(asyncio) - 适用于高并发 I/O 操作,如爬虫、异步网络服务。
15.2 Python 线程(threading 模块)
适用场景:网络请求、文件读写等 I/O 密集型任务。
15.2.1 创建线程
import threading
def print_numbers():
for i in range(5):
print(f"Number: {i}")
# 创建线程
thread = threading.Thread(target=print_numbers)
thread.start()
# 主线程继续执行
print("主线程执行中...")
thread.join() # 等待子线程执行完毕
print("所有线程执行完毕!")
15.2.2 线程锁(避免资源竞争)
多个线程同时修改共享变量可能导致数据不一致,需要使用 Lock
进行同步:
import threading
counter = 0
lock = threading.Lock()
def increase_counter():
global counter
for _ in range(1000000):
with lock:
counter += 1
# 创建两个线程
t1 = threading.Thread(target=increase_counter)
t2 = threading.Thread(target=increase_counter)
t1.start()
t2.start()
t1.join()
t2.join()
print(f"最终计数值:{counter}") # 可能小于 2000000(如果没有锁)
15.3 Python 进程(multiprocessing 模块)
适用场景:CPU 密集型任务(数学计算、数据分析)。
15.3.1 创建进程
import multiprocessing
def compute_square(num):
print(f"平方:{num * num}")
if __name__ == "__main__":
process = multiprocessing.Process(target=compute_square, args=(5,))
process.start()
process.join()
15.3.2 进程池(Pool)
进程池可以同时执行多个任务,提高计算效率:
import multiprocessing
def compute_square(num):
return num * num
if __name__ == "__main__":
with multiprocessing.Pool(4) as pool:
results = pool.map(compute_square, range(10))
print(results)
15.4 Python 异步编程(asyncio 模块)
适用场景:爬虫、高并发网络请求、WebSocket 通信等。
15.4.1 定义异步函数
import asyncio
async def say_hello():
await asyncio.sleep(1)
print("Hello, asyncio!")
asyncio.run(say_hello())
15.4.2 异步执行多个任务
import asyncio
async def task(name, seconds):
print(f"任务 {name} 开始...")
await asyncio.sleep(seconds)
print(f"任务 {name} 结束")
async def main():
await asyncio.gather(task("A", 2), task("B", 1))
asyncio.run(main())
15.5 选择合适的并发方式
方式 | 适用场景 | 主要特点 |
---|---|---|
多线程 (threading ) | I/O 密集型(网络请求、文件读写) | 受 GIL 限制,适用于并发但不适合并行 |
多进程 (multiprocessing ) | CPU 密集型(数据计算、视频处理) | 每个进程有独立的 GIL,可以真正并行执行 |
异步编程 (asyncio ) | 高并发 I/O(爬虫、Web 服务器) | 需要支持 await 关键字,适用于 I/O 操作 |
15.6 小结
本章介绍了:
- 多线程(threading) 适用于 I/O 任务。
- 多进程(multiprocessing) 适用于 CPU 计算任务。
- 异步编程(asyncio) 适用于高并发网络 I/O。