本文目录导读:

我来详细讲讲Python多线程效率提升的关键点。
理解GIL的影响
首先要知道Python的GIL(全局解释器锁)限制:
# CPU密集型任务 - 多线程效果差
def cpu_intensive():
for i in range(10**7):
i * i
# IO密集型任务 - 多线程效果好
def io_intensive():
import time
time.sleep(1) # IO等待不占用CPU
针对不同类型的优化策略
IO密集型任务 - 使用多线程
import threading
import requests
from concurrent.futures import ThreadPoolExecutor
# ✅ 推荐方式:使用线程池
def download_urls(urls):
with ThreadPoolExecutor(max_workers=10) as executor:
results = executor.map(requests.get, urls)
return list(results)
CPU密集型任务 - 使用多进程
from multiprocessing import Pool
def cpu_task(data):
# CPU密集计算
return sum(i * i for i in range(data))
# ✅ 使用多进程绕过GIL
with Pool(processes=4) as pool:
results = pool.map(cpu_task, [10**7] * 4)
关键优化技巧
1 合理设置线程数
import os
from concurrent.futures import ThreadPoolExecutor
# 对于IO密集型
io_threads = os.cpu_count() * 5 # 通常是CPU核心数的5倍
# 对于CPU密集型
cpu_threads = os.cpu_count() # 等于CPU核心数
# 动态调整策略
class AdaptiveThreadPool:
def __init__(self, task_type='io'):
if task_type == 'io':
self.max_workers = os.cpu_count() * 5
else:
self.max_workers = os.cpu_count()
2 使用异步IO提升性能
import asyncio
import aiohttp
async def fetch_url(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
# 比多线程更高效的异步方案
async def main(urls):
tasks = [fetch_url(url) for url in urls]
return await asyncio.gather(*tasks)
# 运行
results = asyncio.run(main(url_list))
3 避免频繁的锁竞争
import threading
# ❌ 不好的方式:频繁加锁
def bad_counter():
lock = threading.Lock()
counter = 0
def increment():
nonlocal counter
for _ in range(1000):
with lock: # 每次循环都加锁
counter += 1
# ✅ 好的方式:减少锁竞争
def good_counter():
lock = threading.Lock()
counter = 0
def increment():
nonlocal counter
local_count = 0
for _ in range(1000):
local_count += 1 # 本地累加
with lock: # 只在最后加一次锁
counter += local_count
4 使用线程安全的数据结构
from collections import deque
from queue import Queue
import threading
# ✅ 使用专门的线程安全队列
task_queue = Queue(maxsize=100)
# ❌ 避免使用普通列表
# shared_list = [] # 不安全
class TaskProcessor:
def __init__(self):
self.results = []
self.lock = threading.Lock()
def process(self, item):
# 处理任务
result = item * 2
with self.lock:
self.results.append(result)
实际性能优化案例
1 爬虫优化
import asyncio
import aiohttp
from asyncio import Semaphore
class OptimizedCrawler:
def __init__(self, max_concurrent=10):
self.semaphore = Semaphore(max_concurrent)
self.session = None
async def fetch_with_limit(self, url):
async with self.semaphore: # 控制并发数
async with self.session.get(url) as response:
return await response.text()
async def crawl(self, urls):
async with aiohttp.ClientSession() as session:
self.session = session
tasks = [self.fetch_with_limit(url) for url in urls]
return await asyncio.gather(*tasks)
2 数据库批量操作
import threading
from concurrent.futures import ThreadPoolExecutor
import sqlite3
class BatchDatabaseWriter:
def __init__(self, batch_size=100):
self.batch_size = batch_size
self.buffer = []
self.lock = threading.Lock()
def insert(self, data):
with self.lock:
self.buffer.append(data)
if len(self.buffer) >= self.batch_size:
self.flush()
def flush(self):
if not self.buffer:
return
# 批量写入数据库
batch = self.buffer[:]
self.buffer = []
# 在单独的线程执行IO操作
threading.Thread(target=self._batch_insert, args=(batch,)).start()
性能监控和调试
import time
from functools import wraps
def measure_time(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
print(f"{func.__name__}: {time.perf_counter() - start:.2f}s")
return result
return wrapper
# 比较不同方案的性能
@measure_time
def test_multithreading():
with ThreadPoolExecutor(max_workers=10) as executor:
list(executor.map(some_task, range(100)))
@measure_time
def test_asyncio():
asyncio.run(main(range(100)))
| 场景 | 推荐方案 | 线程数建议 |
|---|---|---|
| IO密集型(网络请求、文件读写) | 多线程/异步IO | CPU核心数×5 |
| CPU密集型(计算) | 多进程 | CPU核心数 |
| 混合型 | 多进程+异步IO | 根据实际测试 |
最佳实践:
- 先用
concurrent.futures,简单高效 - IO密集型首选
asyncio - 避免共享状态,优先使用队列传递数据
- 使用性能分析工具(
cProfile)找出瓶颈
需要我针对具体的应用场景提供更详细的优化方案吗?