Python 多线程详解(概念、初始化方式、线程间变量传递、线程锁以及一些注意事项)

Python 多线程详解

1. 多线程的概念

在 Python 中,多线程是指在一个进程内同时运行多个线程,以便在某些场景下提升程序的响应能力或并发性。

线程是 CPU 调度的最小单位,而进程是系统资源分配的最小单位。一个进程可以包含多个线程,这些线程共享同一进程的资源(包括内存空间)。

注意 :Python 的 GIL(Global Interpreter Lock,全局解释器锁) 限制了同一时刻只能有一个线程执行 Python 字节码 ,所以多线程在计算密集型任务中无法真正实现并行,更多用于 I/O 密集型任务(例如网络请求、文件读写)。


2. 多线程的初始化

在 Python 中可以使用 threading 模块来创建和管理线程。

2.1 使用 threading.Thread

python 复制代码
import threading
import time

def worker(name):
    print(f"线程 {name} 开始工作")
    time.sleep(1)
    print(f"线程 {name} 工作结束")

# 创建线程对象
t1 = threading.Thread(target=worker, args=("A",))
t2 = threading.Thread(target=worker, args=("B",))

# 启动线程
t1.start()
t2.start()

# 等待线程结束
t1.join()
t2.join()

print("所有线程执行完毕")

关键参数

  • target:线程运行的函数。
  • args:传给函数的参数(元组形式)。
  • kwargs:传给函数的关键字参数。

3. 线程之间的变量传递

3.1 共享变量

线程之间可以共享同一个全局变量(因为它们在同一个进程中),但这会引发 数据竞争 问题。

python 复制代码
import threading

counter = 0  # 全局变量

def increment():
    global counter
    for _ in range(100000):
        counter += 1  # 多线程这里可能会出错

threads = []
for _ in range(5):
    t = threading.Thread(target=increment)
    threads.append(t)
    t.start()

for t in threads:
    t.join()

print("counter =", counter)

上面的代码可能不会得到想象的结果,因为多个线程同时修改 counter 会产生 竞态条件


4. 线程锁(Lock)

为避免数据竞争,我们需要使用 (Lock)来确保某段代码同一时刻只有一个线程能执行。

python 复制代码
import threading

counter = 0
lock = threading.Lock()

def safe_increment():
    global counter
    for _ in range(100000):
        with lock:  # 自动 acquire/release
            counter += 1

threads = []
for _ in range(5):
    t = threading.Thread(target=safe_increment)
    threads.append(t)
    t.start()

for t in threads:
    t.join()

print("counter =", counter)  # 结果正确

4.1 Lock 的用法

python 复制代码
lock = threading.Lock()

# 方式1
lock.acquire()
try:
    # 临界区代码
    pass
finally:
    lock.release()

# 方式2 (推荐)
with lock:
    # 临界区代码
    pass

5. 线程间通信

除了共享变量,还可以使用 队列(Queue) 来安全地进行线程间数据传递。

python 复制代码
import threading
import queue
import time

q = queue.Queue()

def producer():
    for i in range(5):
        q.put(i)
        print(f"生产数据 {i}")
        time.sleep(0.2)

def consumer():
    while True:
        item = q.get()
        if item is None:  # 遇到 None 退出
            break
        print(f"消费数据 {item}")
        time.sleep(0.3)
        q.task_done()

t1 = threading.Thread(target=producer)
t2 = threading.Thread(target=consumer)

t1.start()
t2.start()

t1.join()
q.put(None)  # 通知消费者退出
t2.join()

优点queue.Queue() 是线程安全的,内部已经做好了加锁处理,无需手动使用 Lock。


6. 守护线程(Daemon Thread)

守护线程会在主线程结束时自动退出。

python 复制代码
t = threading.Thread(target=worker)
t.daemon = True  # 设为守护线程
t.start()

适合做后台任务,例如日志记录或心跳检测。


7. 线程池(ThreadPoolExecutor)

如果需要频繁创建和销毁线程,可以使用线程池来提升性能。

python 复制代码
from concurrent.futures import ThreadPoolExecutor

def task(name):
    print(f"{name} 开始")
    return f"{name} 完成"

with ThreadPoolExecutor(max_workers=3) as executor:
    futures = [executor.submit(task, f"任务{i}") for i in range(5)]
    for future in futures:
        print(future.result())

8. 总结与建议

  • 计算密集型任务 :推荐使用多进程(multiprocessing)而不是多线程,避免 GIL 限制。
  • I/O 密集型任务 :推荐使用多线程或异步(asyncio)。
  • 使用 LockQueue 解决数据竞争和线程安全问题。
  • 合理规划线程数量,不要盲目创建过多线程。
  • 可以用 ThreadPoolExecutor 简化线程管理。
相关推荐
小二·4 小时前
Python Web 开发进阶实战:性能压测与调优 —— Locust + Prometheus + Grafana 构建高并发可观测系统
前端·python·prometheus
七牛云行业应用6 小时前
重构实录:我删了 5 家大模型 SDK,只留了 OpenAI 标准库
python·系统架构·大模型·aigc·deepseek
知乎的哥廷根数学学派6 小时前
基于多模态特征融合和可解释性深度学习的工业压缩机异常分类与预测性维护智能诊断(Python)
网络·人工智能·pytorch·python·深度学习·机器学习·分类
一人の梅雨6 小时前
亚马逊SP-API商品详情接口轻量化实战:合规与商业价值提取指南
python
袁气满满~_~8 小时前
Python数据分析学习
开发语言·笔记·python·学习
axinawang8 小时前
二、信息系统与安全--考点--浙江省高中信息技术学考(Python)
python·浙江省高中信息技术
寻星探路8 小时前
【算法专题】滑动窗口:从“无重复字符”到“字母异位词”的深度剖析
java·开发语言·c++·人工智能·python·算法·ai
Dxy12393102168 小时前
python连接minio报错:‘SSL routines‘, ‘ssl3_get_record‘, ‘wrong version number‘
开发语言·python·ssl
吨吨不打野9 小时前
CS336——2. PyTorch, resource accounting
人工智能·pytorch·python
___波子 Pro Max.9 小时前
Python文件读取代码中strip()的作用
python