python高级特性二
python中的GIL(全局解释器锁)
GIL是 CPython 解释器中的一个互斥锁,线程必须先获取 GIL,才能执行 Python 字节码,确保同一时刻只有一个线程执行 Python 字节码。线程执行一定数量的字节码(或遇到 I/O 操作)后,会释放 GIL,让其他线程有机会运行。也就是说在 CPU 密集型任务中,Python 无法真正并行执行多线程代码。GIL导致多线程在单核 CPU 上可以交替执行,但在多核 CPU 上也无法真正并行。
GIL的优点:
✅简化 CPython 实现,避免复杂的线程同步问题。
✅ 提高单线程性能,减少锁竞争开销。
✅ 保护 Python 对象的内存安全。
缺点
❌ 多线程无法真正并行执行(CPU 密集型任务性能受限)。
❌ 多线程在CPU密集型任务中可能比单线程更慢(线程切换开销)。
❌ 限制了 Python 在高并发计算场景的应用(如机器学习)。
CPU 密集型任务:
import threading
import timedef count(n):while n > 0:n -= 1# 单线程
start = time.time()
count(100000000)
print("单线程耗时:", time.time() - start) # 约 5 秒# 多线程(由于 GIL,不会更快)
start = time.time()
t1 = threading.Thread(target=count, args=(50000000,))
t2 = threading.Thread(target=count, args=(50000000,))
t1.start(); t2.start()
t1.join(); t2.join()
print("多线程耗时:", time.time() - start) # 可能约 5.5 秒
I/O 密集型任务
在 I/O 操作(如网络请求、文件读写)时,线程会主动释放 GIL,因此多线程仍然可以提升性能:
import threading
import requestsdef fetch_url(url):response = requests.get(url)print(f"{url} 请求完成")urls = ["https://example.com", "https://google.com", "https://github.com"]# 单线程
start = time.time()
for url in urls:fetch_url(url)
print("单线程耗时:", time.time() - start) # 约 3 秒# 多线程
start = time.time()
threads = []
for url in urls:t = threading.Thread(target=fetch_url, args=(url,))t.start()threads.append(t)
for t in threads:t.join()
print("多线程耗时:", time.time() - start) # 约 1 秒
解决办法:
1、多进程(multiprocessing):适用于CPU 密集型计算(如机器学习)
每个 Python 进程有独立的 GIL,可以真正并行:
from multiprocessing import Pooldef compute(n):return sum(range(n))if __name__ == "__main__":with Pool(4) as p:results = p.map(compute, [10**7, 10**7, 10**7, 10**7])print(results)
2、 使用 C 扩展:
# Cython 示例
with nogil:# 这里可以执行无 GIL 的 C 代码pass
3、使用异步编程(asyncio):适用于高并发 I/O 操作、Web 服务器、爬虫、高并发网络请求。
import asyncioasync def fetch(url):print(f"正在请求 {url}")await asyncio.sleep(1) # 模拟 I/O 操作return f"{url} 完成"async def main():tasks = [fetch("https://example.com"), fetch("https://google.com")]results = await asyncio.gather(*tasks)print(results)asyncio.run(main())