python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python GIL锁详解

Python基础之GIL锁是什么及其对爬虫的影响详析

作者:遇事不決洛必達

GIL是Python解释器中的一个重要组成部分,它是一把全局锁,用于确保在同一时刻只有一个线程可以执行Python字节码,这篇文章主要介绍了Python基础之GIL锁是什么及其对爬虫影响的相关资料,需要的朋友可以参考下

1. GIL 是什么?

GIL 全称 Global Interpreter Lock,全局解释器锁

CPython 解释器中,同一时刻通常只允许 一个线程执行 Python 字节码

也就是说,即使你开启了多个线程:

import threading

这些线程在执行 Python 代码时,并不是多个线程真正同时跑 Python 字节码,而是需要轮流拿到 GIL 才能执行。

2. 为什么 Python 要有 GIL?

主要原因是:保证 CPython 内部对象的线程安全

Python 中很多对象都有引用计数,例如:

a = []
b = a

CPython 需要维护对象的引用计数。如果多个线程同时修改引用计数,就可能出错。

为了简单、稳定地保护解释器内部状态,CPython 使用了 GIL。

3. GIL 对爬虫有什么影响?

爬虫大多数场景属于 IO 密集型任务,比如:

这些操作大部分时间都在“等待”,不是一直占用 CPU。

所以:

GIL 对普通爬虫影响不大,多线程仍然有效。

例如:

import requests
from concurrent.futures import ThreadPoolExecutor

def fetch(url):
    r = requests.get(url, timeout=10)
    return r.text

urls = ["https://example.com"] * 20

with ThreadPoolExecutor(max_workers=10) as pool:
    results = list(pool.map(fetch, urls))

这个场景下,多线程可以提升效率,因为线程在等待网络响应时会释放 GIL,让其他线程继续执行。

4. GIL 对哪些爬虫场景影响较大?

如果爬虫中包含大量 CPU 密集型任务,GIL 影响就比较明显。

比如:

例如:

def calc_sign(data):
    # 大量 CPU 计算
    pass

这种任务用多线程不一定能提升性能,因为多个线程会争抢 GIL。

5. 如何绕过 GIL?

方案一:使用多进程

多进程是最常见方案。

每个进程都有自己独立的 Python 解释器和 GIL,因此可以真正利用多核 CPU。

from multiprocessing import Pool

def parse_html(html):
    # CPU密集型解析
    return html.count("div")

if __name__ == "__main__":
    html_list = ["<div></div>" * 100000] * 8

    with Pool(4) as pool:
        result = pool.map(parse_html, html_list)

    print(result)

适合:

方案二:使用 C/C++ 扩展或第三方库

部分底层库会释放 GIL,例如:

如果核心计算在 C 层完成,可能不会长期占用 GIL。

方案三:把任务拆给外部服务

例如爬虫项目中:

这种方式适合大型项目。

6. 总结

GIL 是 CPython 中的全局解释器锁,它保证同一时刻只有一个线程执行 Python 字节码。
对爬虫来说,如果是网络请求、数据库读写这类 IO 密集型任务,影响不大,因为线程等待 IO 时会释放 GIL,多线程仍然能提升效率。
但如果爬虫中有大量 CPU 密集型任务,比如 JS 加密计算、图片识别、大规模数据清洗,多线程会受 GIL 限制,无法充分利用多核。
解决方式包括使用多进程、asyncio 异步 IO、C 扩展库,或者将计算任务拆分到 Node、Go 等外部服务中。

到此这篇关于Python基础之GIL锁是什么及其对爬虫影响的文章就介绍到这了,更多相关Python GIL锁详解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文