一、GIL锁
1、全局解释器锁(Global Interpreter Lock,简称 GIL)
GIL 是一种用于保护 Python 解释器在多线程环境下的数据完整性的机制。GIL 只存在是 CPython 解释器中,即官方的 Python 解释器实现
GIL 是一个互斥锁,你可以使用多线程来并发处理任务,但在同一时刻只能有一个线程在执行 Python 字节码。
2、存在的背景
GIL 的存在主要是因为 CPython 的内存管理机制(垃圾回收机制,python有一个垃回收线程)并不是线程安全的。
Python 中的对象引用计数机制(reference counting)是一种快速且高效的垃圾回收机制,但它对于多线程环境来说需要保证引用计数的一致性,这就需要 GIL 来确保同一时间只有一个线程能够访问和修改对象的引用计数。
由于 GIL 的存在,导致了 Python 在 CPU 密集型任务上的多线程性能并不理想。因为在这种情况下,即使使用了多个线程,由于 GIL 的限制,多个线程也不能真正并行执行,只能交替执行,因此无法充分利用多核 CPU 的优势。
然而,GIL 在 I/O 密集型任务上的影响较小。当线程执行 I/O 操作(如文件读写、网络请求)时,线程会主动释放 GIL,让其他线程有机会执行,从而提高了并发性能。
需要注意的是,GIL 只存在于 CPython 解释器中。其他一些 Python 解释器实现(如 Jython、IronPython)没有 GIL,它们可以更好地利用多线程并发执行。
GIL 是 Python 解释器中的一种机制,用于保护解释器在多线程环境下的数据一致性。
虽然 GIL 限制了多线程的并行性能,但在 I/O 密集型任务中仍然可以提供一定的并发优势。
如果你需要在 Python 中处理 CPU 密集型任务,并发执行的需求较大,可以考虑使用多进程、异步编程或者使用其他 Python 解释器实现来绕过 GIL 的限制。
案例
创建了5个线程,每个线程都执行一个自增函数,该函数将一个全局计数器 counter
的值自增100万次。
由于 GIL 的限制,这段代码在多线程环境下并不能实现预期的并行效果。最终输出的计数器值通常会小于500万,而不是我们期望的500万(即每个线程自增100万次,共5个线程)。
这是因为 GIL 会确保在任何同一时间内只有一个线程在执行 Python 代码,导致多个线程无法同时访问和修改共享的计数器变量。没有抢到GIL锁的线程就会被释放掉。线程会交替地获取和释放 GIL,导致了部分线程的执行时间被浪费,没有执行。
import threading import time # 全局变量 counter = 0 # 自增函数 def increment(): global counter for i in range(1000000): counter += 1 # 创建并启动多个线程 threads = [] for i in range(5): thread = threading.Thread(target=increment) thread.start() threads.append(thread) # 等待所有线程执行完成 for thread in threads: thread.join() # 输出最终的计数器值 print("Final counter value:", counter) # Final counter value: 2301450
二、互斥锁
1、
标签:解释器,多线程,Python,counter,互斥,线程,GIL From: https://www.cnblogs.com/dgp-zjz/p/17535159.html