问题:
- 现实场景:爬虫需要并发请求 100 个 URL / GUI 程序需避免界面卡顿
- Python 的两种并发方案对比:多线程 (threading) vs 多进程 (multiprocessing)
- 抛出核心问题:为什么 Python 多线程有时比单线程更慢?
Python多线程编程基础:快速上手
- 创建线程的两种方式
- 直接传入目标函数
- 继承Tread类
python
def worker(task_id):
print(f"Processing task {task_id}")
thread = Thread(target=worker, args=(1,))
from threading import Thread
class MyThread(Thread):
def run(self):
print(f"Thread {self.name} is running")
thread = MyThread()
thread.start() # 启动线程而非直接调用run()
- 线程生命周期管理
- start() vs join()
css
threads = [Thread(target=worker, args=(i,)) for i in range(5)]
for t in threads: t.start()
for t in threads: t.join() # 等待所有线程完成
- 守护线程(daemon thread)的使用场景
ini
t = Thread(target=background_task, daemon=True)
t.start() # 主线程退出时自动终止
线程同步
当多个线程对共享资源进行操作时,可能会引发数据不一致的问题,这时就需要进行线程同步。Python提供了多种同步原语:
- Lock锁
csharp
import threading
counter = 0
lock = threading.Lock()
def increment():
global counter
for _ in range(100000):
lock.acquire() # 获取锁
try:
counter += 1
finally:
lock.release() # 释放锁
# 创建并启动线程
threads = [threading.Thread(target=increment) for _ in range(2)]
for t in threads:
t.start()
for t in threads:
t.join()
print(f'最终结果: {counter}') # 结果应为200000
- RLock可重入锁 同一个线程可以多次获得RLock,适合在递归或者嵌套场景中使用
- Semaphore信号量 用于控制同时访问资源的线程数量
python
semaphore = threading.Semaphore(3) # 最多允许3个线程同时访问
def worker():
with semaphore: # 获取信号量
print('正在访问资源...')
- Condition条件变量 用于线程间通信和协调
python
condition = threading.Condition()
def consumer():
with condition:
condition.wait() # 等待通知
print('收到通知,开始消费')
def producer():
with condition:
print('生产完成,发送通知')
condition.notify() # 发送通知
线程间通信Queue vs 共享变量
线程间可以通过共享变量和队列Queue来交换数据,使用queue.Queue()是线程安全的方式
python
from queue import Queue
import threading
def producer(queue):
for item in range(5):
queue.put(item)
print(f'生产: {item}')
def consumer(queue):
while True:
item = queue.get()
print(f'消费: {item}')
queue.task_done() # 通知队列任务已完成
q = Queue()
t1 = threading.Thread(target=producer, args=(q,))
t2 = threading.Thread(target=consumer, args=(q,), daemon=True) # 守护线程
t1.start()
t2.start()
t1.join() # 等待生产者线程完成
q.join() # 等待队列中的所有任务被处理完