Python29_并发编程

Python29_并发编程

### 文章目录

  • [Python29_并发编程](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [@[toc]](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [基本概念](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [1 并发 vs 并行](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [2 Python 的并发模型](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [多线程编程](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [1 基本使用](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [2 线程同步](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [3 线程间通信](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [多进程编程](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [1 基本使用](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [2 进程池](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [3 进程间通信](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [异步IO(asyncio)](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [1 基本概念](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [2 基本使用](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [3 高级特性](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [并发编程选择指南](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [实际应用示例](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [1 并发下载器](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [2 并行计算](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)
  • [常见问题](#文章目录 Python29_并发编程 @[toc] 基本概念 1 并发 vs 并行 2 Python 的并发模型 多线程编程 1 基本使用 2 线程同步 3 线程间通信 多进程编程 1 基本使用 2 进程池 3 进程间通信 异步IO(asyncio) 1 基本概念 2 基本使用 3 高级特性 并发编程选择指南 实际应用示例 1 并发下载器 2 并行计算 常见问题)

并发编程 是现代软件开发中提高程序性能的重要手段。Python提供了多种并发编程方式,包括多线程、多进程和异步IO。

基本概念

1 并发 vs 并行
  • 并发(Concurrency): 多个任务交替执行,看起来像是同时运行

  • 并行(Parallelism): 多个任务真正同时执行,需要多核CPU支持

2 Python 的并发模型
  • I/O密集型任务: 适合使用多线程或异步IO

  • CPU密集型任务: 适合使用多进程

多线程编程

Python通过threading模块提供线程支持,但由于GIL(全局 解释器 锁)的存在,多线程不适合CPU密集型任务。

1 基本使用
python 复制代码
import threading
import time
 
def task(name):
    print(f"任务 {name} 开始")
    time.sleep(2)  # 模拟I/O操作
    print(f"任务 {name} 完成")
 
# 创建线程
threads = []
for i in range(3):
    t = threading.Thread(target=task, args=(f"Thread-{i}",))
    threads.append(t)
    t.start()
 
# 等待所有线程完成
for t in threads:
    t.join()
 
print("所有任务完成")
2 线程同步
  • 使用锁Lock/RLock
python 复制代码
# 使用锁Lock/RLock
import threading
import time

counter = 0
lock = threading.Lock()


def increment():
    global counter
    for _ in range(100000):
        with lock:  # 自动获取和释放锁
            counter += 1


if __name__ == '__main__':
    thread_num = 5
    print(f"{thread_num}个线程,开始时间: {time.time():.2f}")
    threads = []
    for _ in range(thread_num):
        t = threading.Thread(target=increment)
        threads.append(t)
        t.start()

    for t in threads:
        t.join()

    print(f"最终计数器值: {counter}")  # 应该是500000
    print(f"{thread_num}个线程,结束时间: {time.time():.2f}")
  • 使用Semaphore信号量
  • 注意:如果信号量不等于1,还是不能解决并发导致的【不安全的数据类型操作】问题
python 复制代码
# 使用Semaphore信号量
import threading
import time

counter = 0
lock = threading.Lock()


def increment(thread_name):
    global counter
    for _ in range(20):
        with semaphore:  # 自动获取和释放锁
            print(f"{thread_name} 正在使用资源 ")
            counter += 1
            print(f"{thread_name} 释放资源 ")


if __name__ == '__main__':
    # 使用信号量(如果信号量不等于1,还是不能解决并发导致的【不安全的数据类型操作】问题)
    semaphore = threading.Semaphore(3)  # 最多3个线程同时访问
    thread_num = 10
    threads = []
    print(f"{thread_num}个线程,开始时间: {time.time():.2f}")
    for i in range(thread_num):
        t = threading.Thread(target=increment, args=(f"ThreadName-{i}",))
        threads.append(t)
        t.start()

    for t in threads:
        t.join()

    print(f"最终计数器值: {counter}")  # 应该是500000
    print(f"{thread_num}个线程,结束时间: {time.time():.2f}")

3 线程间通信
python 复制代码
# 使用队列
import queue
 
def producer(q):
    for i in range(5):
        print(f"生产物品 {i}")
        q.put(i)
        time.sleep(0.5)
    q.put(None)  # 结束信号
 
def consumer(q):
    while True:
        item = q.get()
        if item is None:
            break
        print(f"消费物品 {item}")
        time.sleep(1)
 
q = queue.Queue()
threading.Thread(target=producer, args=(q,)).start()
threading.Thread(target=consumer, args=(q,)).start()

多进程编程

多进程可以绕过GIL限制,适合CPU密集型任务,但进程间通信开销较大。

1 基本使用
python 复制代码
from multiprocessing import Process
import os
 
def cpu_bound_task(n):
    print(f"进程 {os.getpid()} 计算 {n} 的平方")
    return n * n
 
if __name__ == '__main__':
    processes = []
    for i in range(4):
        p = Process(target=cpu_bound_task, args=(i,))
        processes.append(p)
        p.start()
    
    for p in processes:
        p.join()
2 进程池
python 复制代码
from multiprocessing import Pool
 
def square(x):
    return x * x
 
if __name__ == '__main__':
    with Pool(4) as pool:  # 4个工作进程
        # map方法
        results = pool.map(square, range(10))
        print(results)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
        
        # apply_async方法
        result = pool.apply_async(square, (10,))
        print(result.get())  # 100
3 进程间通信
python 复制代码
from multiprocessing import Process, Queue
 
def worker(q):
    while True:
        item = q.get()
        if item is None:
            break
        print(f"处理: {item}")
 
if __name__ == '__main__':
    q = Queue()
    p = Process(target=worker, args=(q,))
    p.start()
    
    for i in range(5):
        q.put(i)
    
    q.put(None)  # 结束信号
    p.join()

异步IO(asyncio)

asyncio是Python3.4引入的 标准库 ,适合I/O密集型任务,使用单线程实现高并发。

1 基本概念
  • 协程(Coroutine) : 使用async def定义的函数

  • 事件循环(Event Loop): 协程的调度器

  • Future/Task: 表示异步操作的结果

2 基本使用
python 复制代码
import asyncio

async def fetch_data(url):
    print(f"开始获取 {url}")
    await asyncio.sleep(2)  # 模拟I/O操作
    print(f"完成获取 {url}")
    return f"{url} 的数据"

async def main():
    # 顺序执行
    result1 = await fetch_data("url1")
    result2 = await fetch_data("url2")
    print(result1, result2)
    
    # 并发执行
    task1 = asyncio.create_task(fetch_data("url3"))
    task2 = asyncio.create_task(fetch_data("url4"))
    await task1
    await task2
    
    # 使用gather
    results = await asyncio.gather(
        fetch_data("url5"),
        fetch_data("url6"),
        fetch_data("url7")
    )
    print(results)

asyncio.run(main())
3 高级特性
python 复制代码
# 超时控制
async def slow_operation():
    await asyncio.sleep(5)
    return "完成"
 
async def main():
    try:
        result = await asyncio.wait_for(slow_operation(), timeout=3.0)
    except asyncio.TimeoutError:
        print("操作超时")
 
# 事件循环控制
async def periodic_task():
    while True:
        print("执行周期性任务")
        await asyncio.sleep(1)
 
async def main():
    task = asyncio.create_task(periodic_task())
    await asyncio.sleep(5)
    task.cancel()
    try:
        await task
    except asyncio.CancelledError:
        print("任务已取消")

并发编程选择指南

方法 适用场景 优点 缺点
多线程 I/O密集型,GUI应用 轻量级,共享内存方便 受GIL限制,不适合CPU密集型
多进程 CPU密集型任务 绕过GIL,利用多核 内存开销大,进程间通信复杂
异步IO 高并发I/O操作,网络应用 高效,单线程高并发 需要特殊库支持,学习曲线陡峭

实际应用示例

1 并发下载器
python 复制代码
import aiohttp
import asyncio
 
async def download(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            content = await response.read()
            print(f"下载 {url} 完成,长度: {len(content)}")
            return content
 
async def main():
    urls = [
        'https://www.python.org',
        'https://www.google.com',
        'https://www.github.com'
    ]
    tasks = [download(url) for url in urls]
    await asyncio.gather(*tasks)
 
asyncio.run(main())
2 并行计算
python 复制代码
from multiprocessing import Pool
import math
 
def is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(math.sqrt(n)) + 1):
        if n % i == 0:
            return False
    return True
 
if __name__ == '__main__':
    numbers = range(1000000, 1000100)
    with Pool(4) as pool:
        results = pool.map(is_prime, numbers)
        primes = [n for n, prime in zip(numbers, results) if prime]
        print(f"找到 {len(primes)} 个质数")

常见问题

  1. GIL限制

    • 使用多进程代替多线程处理CPU密集型任务

    • 使用C扩展释放GIL

  2. 死锁问题

    • 按固定顺序获取锁

    • 使用带超时的锁

  3. 资源竞争

    • 使用线程安全的数据结构

    • 尽量减少共享状态

  4. 协程阻塞

    • 避免在协程中使用阻塞I/O

    • 使用专门的异步库(aiohttp, asyncpg等)

通过合理选择并发模型并正确实现,可以显著提高Python程序的性能,特别是在处理I/O密集型或CPU密集型任务时。


相关推荐
阿凤211 小时前
后端返回文件二进制流
开发语言·前端·javascript·uniapp
小天互连即时通讯1 小时前
政企信创即时通讯选型参考
大数据·网络·人工智能
Leinwin1 小时前
GPT-6 API接入完全指南:Symphony架构下的多模态调用与最佳实践
后端·python·flask
m0_748839491 小时前
PHP跨平台部署AI应用_Docker容器化方案【教程】
jvm·数据库·python
ฅ ฅBonnie1 小时前
vLLM 推理后端简介
人工智能·python·算法
历程里程碑1 小时前
Linux 50 IP协议深度解析:从报头结构到子网划分与NAT
java·linux·开发语言·网络·c++·python·智能路由器
半壶清水1 小时前
[软考网规考点笔记]-局域网之VLAN
网络·笔记·网络协议·tcp/ip
Just right1 小时前
pycharm卡死在Connected to pydev debugger
ide·python·pycharm
aq55356001 小时前
Laravel2.x:被遗忘的PHP框架遗珠
开发语言·汇编·c#