Python多线程全面解析,从使用到GIL的底层逻辑

问题:

  • 现实场景:爬虫需要并发请求 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()   # 等待队列中的所有任务被处理完
相关推荐
止语Lab2 小时前
好的 DX 不等于少写代码——三种语言的摩擦力设计课
后端
吃饱了得干活2 小时前
别再手动解析 LLM 输出了!LangChain 四种结构化输出方案对比
后端·python·langchain
程序员天天困2 小时前
Arthas trace 命令怎么用?一行定位最慢那行代码
jvm·后端
Huiturn2 小时前
GPT 5.6 连续编码 10 小时,纯 Python 啃下 Word 二进制格式——doc2docx 实现拆解
后端
用户298698530142 小时前
Python 实现 Excel 与 Markdown 互转的实用指南
后端·python·excel
用户77283104908402 小时前
krono-job:零侵入、单二进制交付的分布式任务调度平台(开源)
后端
Conan在掘金2 小时前
鸿蒙报错速查:Function lacks ending return statement,返回路径漏 return 就炸,根因 + 真解法
后端
人间凡尔赛3 小时前
AI-Native 云原生架构:2026 年从容器编排到智能体编排的范式革命
后端·云原生·架构
IT_陈寒3 小时前
Vue的响应式让我加班到凌晨3点,原来问题出在这
前端·人工智能·后端
卷无止境3 小时前
提升 Python 代码健壮性的方法大盘点
后端·python