Python并发编程基础主要包括以下几个方面:
- 多线程(threading)
- 多进程(multiprocessing)
- 协程(asyncio)
- 线程池和进程池
- 同步与异步
- 锁(Lock)和信号量(Semaphore)
- 条件变量(Condition)
- 队列(Queue)
首先要知道的概念:串行(可以理解为在X轴,随着时间在运行代码,一段代码结束,下一段代码继续运行),并行(可以理解为在Y轴,同一时间,多段代码同时运行,运行数量少于cpu核数),并发(XY周同时运行,指的是任务数多余 cpu 核数,通过操作系统的各种任务调度算法,实现用多个任 务“一起”执行)
多线程(threading)
import threading
def worker():
"""线程工作函数"""
print("线程执行中...")
# 创建两个线程
t1 = threading.Thread(target=worker)
t2 = threading.Thread(target=worker)
# 启动线程
t1.start()
t2.start()
# 等待线程执行完毕
t1.join()
t2.join()
print("所有线程执行完毕")
多进程
import multiprocessing
def worker():
"""进程工作函数"""
print("进程执行中...")
# 创建两个进程
p1 = multiprocessing.Process(target=worker)
p2 = multiprocessing.Process(target=worker)
# 启动进程
p1.start()
p2.start()
# 等待进程执行完毕
p1.join()
p2.join()
print("所有进程执行完毕")
协程(asyncio)
import asyncio
async def worker():
"""协程工作函数"""
print("协程执行中...")
await asyncio.sleep(1)
# 创建事件循环
loop = asyncio.get_event_loop()
# 创建任务列表
tasks = [worker(), worker()]
# 执行任务
loop.run_until_complete(asyncio.wait(tasks))
# 关闭事件循环
loop.close()
print("所有协程执行完毕")
线程池和进程池
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
def worker():
"""工作函数"""
print("工作执行中...")
# 创建线程池
with ThreadPoolExecutor(max_workers=2) as executor:
# 提交任务
futures = [executor.submit(worker) for _ in range(2)]
# 等待任务完成
for future in futures:
future.result()
print("所有线程池任务执行完毕")
# 创建进程池
with ProcessPoolExecutor(max_workers=2) as executor:
# 提交任务
futures = [executor.submit(worker) for _ in range(2)]
# 等待任务完成
for future in futures:
future.result()
print("所有进程池任务执行完毕")
写在最后:
进程:拥有自己独立的堆和栈,既不共享堆,也不共享栈,进程由操作系统调度;进程切 换需要的资源很最大,效率很低 线程:拥有自己独立的栈和共享的堆,共享堆,不共享栈,标准线程由操作系统调度;线 程切换需要的资源一般,效率一般(当然了在不考虑 GIL 的情况下)
协程:拥有自己独立的栈和共享的堆,共享堆,不共享栈,协程由程序员在协程的代码里 显示调度;协程切换任务资源很小,效率高
多进程、多线程根据 cpu 核数不一样可能是并行的,但是协程是在一个线程中 所以是并 发 选择技术考虑的因素:切换的效率、数据共享的问题、 数据安全、是否需要并发