Python多线程是并发编程的重要组成部分,适合处理I/O密集型任务,其核心原理和实战用法是开发者必须掌握的内容。理解GIL的工作机制、threading模块的使用方式以及线程同步的方法,是学好Python多线程的关键。

Python多线程核心原理
GIL全局解释器锁
Python的GIL(Global Interpreter Lock)是CPython解释器引入的机制,同一时刻只有一个线程能执行Python字节码。这意味着在计算密集型任务中,多线程无法利用多核CPU的优势,但在I/O密集型任务中,线程在等待I/O时会释放GIL,多线程仍能提升程序效率。
多线程适用场景
- I/O密集型任务:如网络请求、文件读写、数据库操作等,线程等待I/O时会让出CPU,多线程可提升整体吞吐量
- 需要并发处理多个独立任务的场景,且任务之间没有复杂的共享数据依赖
threading模块基础用法
创建和启动线程
threading模块是Python标准库中实现多线程的核心模块,通过创建Thread对象并调用start方法即可启动线程。
import threading
import time
# 定义线程执行的函数
def task(name):
print(f"线程{name}开始执行")
time.sleep(2) # 模拟I/O等待
print(f"线程{name}执行结束")
if __name__ == "__main__":
# 创建两个线程对象
t1 = threading.Thread(target=task, args=("A",))
t2 = threading.Thread(target=task, args=("B",))
# 启动线程
t1.start()
t2.start()
# 等待所有线程执行完成
t1.join()
t2.join()
print("所有线程执行完成")
线程常用方法
start():启动线程,会自动调用run方法join(timeout=None):阻塞当前线程,直到被调用的线程执行完成或超时is_alive():判断线程是否还在运行threading.current_thread():获取当前执行的线程对象
线程同步机制
当多个线程操作共享数据时,可能会出现数据不一致的问题,需要使用线程同步机制保证数据安全。
互斥锁Lock
Lock是最基础的同步原语,同一时刻只有一个线程能获取锁,其他线程需要等待锁释放。
import threading
import time
# 共享变量
count = 0
# 创建互斥锁
lock = threading.Lock()
def increment():
global count
for _ in range(100000):
# 获取锁
lock.acquire()
try:
count += 1
finally:
# 释放锁,确保无论是否出现异常都能释放
lock.release()
if __name__ == "__main__":
t1 = threading.Thread(target=increment)
t2 = threading.Thread(target=increment)
t1.start()
t2.start()
t1.join()
t2.join()
print(f"最终count值: {count}") # 输出200000,无锁时结果会小于该值
信号量Semaphore
Semaphore用于控制同时访问某个资源的线程数量,比如限制同时发起的数据库连接数。
import threading
import time
# 创建信号量,最多允许3个线程同时访问
semaphore = threading.Semaphore(3)
def access_resource(name):
# 获取信号量
semaphore.acquire()
print(f"线程{name}获取资源访问权限")
time.sleep(1) # 模拟资源使用
print(f"线程{name}释放资源访问权限")
# 释放信号量
semaphore.release()
if __name__ == "__main__":
# 创建5个线程
threads = []
for i in range(5):
t = threading.Thread(target=access_resource, args=(f"T{i}",))
threads.append(t)
t.start()
for t in threads:
t.join()
实战案例:多线程爬取网页
下面通过一个简单的网页爬取案例,演示多线程在I/O密集型任务中的应用。该案例使用多线程同时请求多个网页,提升爬取效率。
import threading
import requests
import time
# 要爬取的网页列表
urls = [
"http://ipipp.com",
"http://ipipp.com/about",
"http://ipipp.com/contact",
"http://ipipp.com/product"
]
def crawl_page(url):
try:
response = requests.get(url, timeout=5)
print(f"爬取{url},状态码: {response.status_code},内容长度: {len(response.text)}")
except Exception as e:
print(f"爬取{url}失败,错误信息: {e}")
if __name__ == "__main__":
start_time = time.time()
threads = []
# 为每个url创建一个线程
for url in urls:
t = threading.Thread(target=crawl_page, args=(url,))
threads.append(t)
t.start()
# 等待所有线程完成
for t in threads:
t.join()
end_time = time.time()
print(f"多线程爬取总耗时: {end_time - start_time:.2f}秒")
# 对比单线程耗时
start_time = time.time()
for url in urls:
crawl_page(url)
end_time = time.time()
print(f"单线程爬取总耗时: {end_time - start_time:.2f}秒")
运行该案例可以看到,多线程爬取的总耗时明显少于单线程,验证了多线程在I/O密集型任务中的效率优势。实际开发中可以根据任务数量调整线程数,避免线程过多导致系统资源消耗过大。
Python多线程threading模块GIL全局解释器锁线程同步并发编程修改时间:2026-07-22 04:39:33