1. Python多线程编程基础
1.1 线程与进程的关系
在计算机科学中,线程和进程是两个核心概念。想象一下,你正在经营一家餐厅:
- 进程就像是整个餐厅的运营系统,它拥有自己的厨房设备(内存)、收银台(I/O资源)和员工管理系统
- 线程则是餐厅里的各个工作人员,他们共享厨房设备,但各自负责不同任务(服务员、厨师、清洁工)
具体到技术层面:
python复制import threading
import multiprocessing
def worker():
print(f"工作线程/进程执行中...")
# 创建线程
t = threading.Thread(target=worker)
t.start()
# 创建进程
p = multiprocessing.Process(target=worker)
p.start()
关键区别在于:
- 进程间内存隔离,线程共享内存
- 创建进程开销大,线程创建轻量
- 进程间通信需要特殊机制(队列、管道等),线程可直接共享变量
1.2 Python的GIL限制
Python的全局解释器锁(GIL)是一个经常被误解的概念。简单来说:
python复制import sys
print(sys.getswitchinterval()) # 默认线程切换间隔(秒)
GIL的影响:
- 同一时刻只有一个线程执行Python字节码
- I/O密集型任务不受太大影响(因为等待I/O时会释放GIL)
- CPU密集型任务建议使用多进程
实际测试案例:
python复制# CPU密集型任务
def cpu_bound(n):
while n > 0:
n -= 1
# I/O密集型任务
def io_bound():
import time
time.sleep(1)
# 测试多线程执行CPU密集型任务
def test_cpu():
import time
start = time.time()
threads = [threading.Thread(target=cpu_bound, args=(10**7,)) for _ in range(4)]
for t in threads:
t.start()
for t in threads:
t.join()
print(f"多线程耗时: {time.time()-start:.2f}秒")
# 对比测试多进程
def test_cpu_mp():
import time
from multiprocessing import Process
start = time.time()
processes = [Process(target=cpu_bound, args=(10**7,)) for _ in range(4)]
for p in processes:
p.start()
for p in processes:
p.join()
print(f"多进程耗时: {time.time()-start:.2f}秒")
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 线程操作进阶
2.1 线程状态管理
线程的生命周期包含多种状态:
python复制import threading
import time
def worker():
print("子线程开始执行")
time.sleep(2)
print("子线程结束执行")
t = threading.Thread(target=worker)
print(f"线程状态: {t.is_alive()}") # False
t.start()
print(f"线程状态: {t.is_alive()}") # True
t.join()
print(f"线程状态: {t.is_alive()}") # False
关键方法解析:
start(): 启动线程,进入就绪状态join(timeout=None): 等待线程结束is_alive(): 检查线程是否在运行daemon: 设置守护线程属性
2.2 线程同步机制
当多个线程访问共享资源时,需要同步机制来避免竞态条件:
python复制import threading
class SharedCounter:
def __init__(self):
self.value = 0
self.lock = threading.Lock()
def increment(self):
with self.lock:
self.value += 1
counter = SharedCounter()
def worker():
for _ in range(100000):
counter.increment()
threads = [threading.Thread(target=worker) for _ in range(4)]
for t in threads:
t.start()
for t in threads:
t.join()
print(f"最终计数: {counter.value}") # 应该是400000
同步原语对比:
| 类型 | 特点 | 适用场景 |
|---|---|---|
| Lock | 基础锁 | 简单互斥 |
| RLock | 可重入锁 | 嵌套锁需求 |
| Condition | 条件变量 | 线程间通知 |
| Semaphore | 信号量 | 限制资源访问数 |
| Event | 事件 | 一次性通知 |
3. 生产者-消费者模式实践
3.1 基础实现
生产者-消费者模式是并发编程中的经典模式:
python复制import queue
import threading
import random
import time
def producer(q, name):
for i in range(5):
item = f"产品-{name}-{i}"
q.put(item)
print(f"生产者 {name} 生产了 {item}")
time.sleep(random.random())
def consumer(q, name):
while True:
item = q.get()
if item is None: # 哨兵值
q.put(item) # 确保其他消费者也能收到
break
print(f"消费者 {name} 消费了 {item}")
time.sleep(random.random() * 2)
q.task_done()
q = queue.Queue(3) # 限制队列大小
producers = [threading.Thread(target=producer, args=(q, f"P-{i}")) for i in range(2)]
consumers = [threading.Thread(target=consumer, args=(q, f"C-{i}")) for i in range(3)]
for t in producers:
t.start()
for t in consumers:
t.start()
for t in producers:
t.join()
q.join() # 等待所有任务完成
for _ in consumers:
q.put(None) # 发送结束信号
for t in consumers:
t.join()
3.2 高级队列应用
Python的queue模块提供了多种队列类型:
python复制from queue import Queue, LifoQueue, PriorityQueue
import threading
# 先进先出队列
fifo_q = Queue()
fifo_q.put(1)
fifo_q.put(2)
print(fifo_q.get()) # 输出1
# 后进先出队列
lifo_q = LifoQueue()
lifo_q.put(1)
lifo_q.put(2)
print(lifo_q.get()) # 输出2
# 优先级队列
pri_q = PriorityQueue()
pri_q.put((3, "低优先级"))
pri_q.put((1, "高优先级"))
pri_q.put((2, "中优先级"))
print(pri_q.get()[1]) # 输出"高优先级"
队列阻塞行为控制:
python复制q = Queue(maxsize=2)
def put_items():
for i in range(4):
try:
q.put(i, block=False) # 非阻塞模式
print(f"成功放入{i}")
except queue.Full:
print(f"队列已满,无法放入{i}")
break
def get_items():
while True:
try:
item = q.get(timeout=1) # 超时1秒
print(f"获取到{item}")
q.task_done()
except queue.Empty:
print("队列已空")
break
put_thread = threading.Thread(target=put_items)
get_thread = threading.Thread(target=get_items)
put_thread.start()
get_thread.start()
4. 线程池高级应用
4.1 线程池核心参数
python复制from concurrent.futures import ThreadPoolExecutor
import time
def task(n):
print(f"开始任务{n}")
time.sleep(2)
return n ** 2
# 核心参数解析
with ThreadPoolExecutor(
max_workers=3, # 最大线程数
thread_name_prefix='my_pool', # 线程名前缀
) as executor:
futures = [executor.submit(task, i) for i in range(5)]
for future in futures:
print(f"结果: {future.result()}")
4.2 异常处理机制
线程池中的异常需要特殊处理:
python复制def might_fail(n):
if n % 2 == 0:
raise ValueError(f"偶数{n}触发错误")
return n * 10
with ThreadPoolExecutor(max_workers=2) as executor:
futures = {executor.submit(might_fail, i): i for i in range(5)}
for future in futures:
try:
result = future.result()
print(f"成功: {result}")
except ValueError as e:
print(f"错误: {e}")
4.3 性能优化技巧
- 线程数设置经验公式:
- I/O密集型:2-5倍CPU核心数
- CPU密集型:等于CPU核心数
python复制import os
import concurrent.futures
def optimal_thread_count():
cpu_count = os.cpu_count()
io_bound = min(32, cpu_count * 5 + 1)
cpu_bound = cp
