1. 什么是线程与 threading? #

注意 GIL: CPython 有全局解释器锁,多线程不能真正并行执行 CPU 计算,但适合 I/O 密集型任务(网络请求、文件读写),因为等待 I/O 时会释放 GIL。

2. 创建线程 #

# 导入 threading 模块
import threading
# 导入 time 模块,用于模拟耗时操作
import time

# 定义工作函数,接收线程名和延迟秒数
def worker(name, delay):
    # 打印线程开始信息
    print(f"线程 {name} 开始")
    # 模拟耗时操作
    time.sleep(delay)
    # 打印线程结束信息
    print(f"线程 {name} 结束")

# 创建线程 A,目标函数为 worker,参数为 ("A", 2)
t1 = threading.Thread(target=worker, args=("A", 2))
# 创建线程 B,延迟 1 秒
t2 = threading.Thread(target=worker, args=("B", 1))

# 启动线程 A
t1.start()
# 启动线程 B
t2.start()
# 等待线程 A 结束
t1.join()
# 等待线程 B 结束
t2.join()
# 所有子线程完成后打印提示
print("所有线程已完成")

常用 API:

方法/属性 作用
start() 启动线程
join(timeout) 等待线程结束
is_alive() 是否仍在运行
threading.current_thread() 获取当前线程
daemon=True 守护线程(程序退出时不等待)

3. 线程同步:Lock #

# 导入 threading 模块
import threading

# 共享计数器,初始值为 0
counter = 0
# 创建互斥锁
lock = threading.Lock()

# 定义自增函数,循环累加 counter
def increment():
    # 声明使用全局变量 counter
    global counter
    # 循环 10 万次
    for _ in range(100_000):
        # 获取锁后修改共享变量,确保原子性
        with lock:
            counter += 1

# 创建 10 个线程执行 increment
threads = [threading.Thread(target=increment) for _ in range(10)]
# 启动所有线程
for t in threads:
    t.start()
# 等待所有线程结束
for t in threads:
    t.join()

# 打印最终计数,应为 1000000
print(counter)

4. 线程间通信:Queue #

# 导入 threading 模块
import threading
# 导入 queue 模块
import queue
# 导入 time 模块
import time

# 创建线程安全队列
q = queue.Queue()

# 生产者:向队列放入 5 条数据
def producer():
    for i in range(5):
        # 放入数据
        q.put(f"数据-{i}")
        # 模拟生产间隔
        time.sleep(0.3)
    # 放入 None 作为结束信号
    q.put(None)

# 消费者:从队列取出并处理数据
def consumer():
    while True:
        # 阻塞等待获取数据
        item = q.get()
        # 收到结束信号则退出循环
        if item is None:
            break
        # 打印消费的数据
        print(f"消费 {item}")

# 启动生产者线程
threading.Thread(target=producer).start()
# 启动消费者线程
threading.Thread(target=consumer).start()

5. GIL 与适用场景 #

任务类型 推荐方案 原因
网络请求、文件 I/O threading 等待时释放 GIL
大量数值计算 multiprocessing 绕过 GIL,真并行
高并发 I/O(大量连接) asyncio 或线程池 见 concurrent 章节

6. 常见错误与注意事项 #

# 定义线程工作函数
def worker():
    try:
        # 执行可能出错的操作
        do_something()
    except Exception:
        # 在线程内捕获并记录异常,避免静默失败
        logger.exception("线程内出错")

7. 总结 #

7.1 速查 #

# 导入 threading 和 Queue
import threading
from queue import Queue

# 创建线程并等待结束
t = threading.Thread(target=func, args=(arg,))
t.start()
t.join()

# 用锁保护共享数据
lock = threading.Lock()
with lock:
    shared_var += 1

# 线程安全队列传数据
q = Queue()
q.put(item)
item = q.get()

7.2 最佳实践 #