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密集型任务时。


相关推荐
MY_TEUCK5 小时前
【Java 后端】SpringBoot 登录认证与会话跟踪实战(JWT + Filter/Interceptor)
java·开发语言·spring boot
Waay6 小时前
“红帽系统管理二”知识点问答题:第11章 管理网络安全
网络·安全·web安全
QQ2422199796 小时前
基于python+微信小程序的家教管理系统_mh3j9
开发语言·python·微信小程序
Yupureki6 小时前
《Linux网络编程》8.网络层IP原理
linux·运维·服务器·网络·ip
沐知全栈开发6 小时前
JavaScript 条件语句
开发语言
RSTJ_16256 小时前
PYTHON+AI LLM DAY THREETY-SEVEN
开发语言·人工智能·python
郝学胜-神的一滴6 小时前
深度学习优化核心:梯度下降与网络训练全解析
数据结构·人工智能·python·深度学习·算法·机器学习
yyuuuzz6 小时前
aws亚马逊入门常见认知误区
运维·服务器·网络·云计算·github·aws
Aision_6 小时前
Agent 为什么需要 Checkpoint?
人工智能·python·gpt·langchain·prompt·aigc·agi
剑锋所指,所向披靡!6 小时前
计算机网络概述
网络·计算机网络