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()   # 等待队列中的所有任务被处理完
相关推荐
南囝coding37 分钟前
一篇文章带你了解清楚,Google Cloud 引发全球互联网服务大面积故障问题
前端·后端
是紫焅呢1 小时前
C函数基础.go
开发语言·后端·青少年编程·golang·学习方法·visual studio code
CodeSheep1 小时前
稚晖君公司再获新投资,yyds!
前端·后端·程序员
未来影子2 小时前
Spring AI Alibaba Graph:中断!人类反馈介入,流程丝滑走完~
后端·ai编程
考虑考虑2 小时前
update语句使用表中的字段更新
数据库·后端
Emma歌小白2 小时前
阿里云安装mysql报错mysql-xxx is filtered out by exclude filtering
后端
AI小智3 小时前
🚀 零成本打造智能AI代理:用 LangGraph + Ollama 构建你的专属“大脑助手”
后端
天天摸鱼的java工程师3 小时前
线程池阻塞与核心线程死亡:我朋友面试被问倒
java·后端·面试