当前位置:首页 > 未命名 > 正文内容

Python 并发编程:多线程、多进程与异步编程详解

廖万里24小时前未命名1

并发编程是提升程序性能的关键技术。Python 提供了多线程、多进程、异步编程三种并发模型,各有适用场景。本文深入解析三种模型的原理与实践。

一、并发 vs 并行

并发:多个任务交替执行,宏观上同时进行,微观上串行。

并行:多个任务真正同时执行,需要多核 CPU 支持。

由于 GIL(全局解释器锁)的存在,Python 多线程无法利用多核实现真正的并行,但在 I/O 密集型场景仍然有效。

二、多线程编程

2.1 基本使用

import threading
import time

def task(name):
    print(f"开始任务: name")
    time.sleep(2)
    print(f"完成任务: name")

# 创建线程
t1 = threading.Thread(target=task, args=("A",))
t2 = threading.Thread(target=task, args=("B",))

# 启动线程
t1.start()
t2.start()

# 等待完成
t1.join()
t2.join()

2.2 线程池

from concurrent.futures import ThreadPoolExecutor
import time

def download(url):
    time.sleep(1)
    return f"下载完成: url"

urls = ["url1", "url2", "url3", "url4", "url5"]

with ThreadPoolExecutor(max_workers=3) as executor:
    results = executor.map(download, urls)
    for result in results:
        print(result)

2.3 线程同步

import threading

counter = 0
lock = threading.Lock()

def increment():
    global counter
    for _ in range(100000):
        with lock:
            counter += 1

threads = [threading.Thread(target=increment) for _ in range(10)]
for t in threads:
    t.start()
for t in threads:
    t.join()

print(f"最终结果: counter")

三、多进程编程

3.1 基本使用

from multiprocessing import Process, Pool
import os

def task(name):
    print(f"进程 os.getpid(): name")

# 创建进程
p1 = Process(target=task, args=("A",))
p2 = Process(target=task, args=("B",))

p1.start()
p2.start()
p1.join()
p2.join()

3.2 进程池

from multiprocessing import Pool

def cpu_intensive(n):
    return sum(i * i for i in range(n))

if __name__ == "__main__":
    numbers = [10000000, 20000000, 30000000, 40000000]
    
    with Pool(processes=4) as pool:
        results = pool.map(cpu_intensive, numbers)
        print(results)

3.3 进程间通信

from multiprocessing import Process, Queue, Manager

def producer(queue):
    for i in range(10):
        queue.put(i)
    queue.put(None)  # 结束信号

def consumer(queue):
    while True:
        item = queue.get()
        if item is None:
            break
        print(f"消费: item")

if __name__ == "__main__":
    queue = Queue()
    p1 = Process(target=producer, args=(queue,))
    p2 = Process(target=consumer, args=(queue,))
    
    p1.start()
    p2.start()
    p1.join()
    p2.join()

四、异步编程

4.1 asyncio 基础

import asyncio

async def fetch_data(url):
    print(f"开始获取: url")
    await asyncio.sleep(1)
    return f"数据: url"

async def main():
    tasks = [
        fetch_data("url1"),
        fetch_data("url2"),
        fetch_data("url3"),
    ]
    results = await asyncio.gather(*tasks)
    print(results)

asyncio.run(main())

4.2 异步 HTTP 请求

import asyncio
import aiohttp

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = ["http://example.com"] * 10
    
    async with aiohttp.ClientSession() as session:
        tasks = [fetch(session, url) for url in urls]
        results = await asyncio.gather(*tasks)
        print(f"获取了 len(results) 个页面")

asyncio.run(main())

4.3 异步生成器

import asyncio

async def async_range(n):
    for i in range(n):
        await asyncio.sleep(0.1)
        yield i

async def main():
    async for num in async_range(5):
        print(num)

asyncio.run(main())

五、选择指南

CPU 密集型:使用多进程,绕过 GIL 限制。

I/O 密集型:使用多线程或异步,推荐异步。

混合型:多进程 + 异步,进程池处理计算,协程处理 I/O。

六、最佳实践

1. 避免共享状态,使用消息传递

2. 合理设置并发数,避免资源耗尽

3. 注意异常处理,避免静默失败

4. 使用上下文管理器确保资源释放

5. 性能测试,选择最优方案

七、总结

Python 并发编程三种模型各有优劣。多线程适合 I/O 密集型,多进程适合 CPU 密集型,异步编程是现代 Python 的推荐方式。理解它们的原理和适用场景,才能选择正确的方案。

本文链接:https://www.kkkliao.cn/?id=778 转载需授权!

分享到:

版权声明:本文由廖万里的博客发布,如需转载请注明出处。


发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。