什么是全局解释器锁,为什么它是一个问题?

关于从Python中删除GIL有很多争议,我想了解为什么这是如此重要。我自己从来没有写过编译器或解释器,所以不要吝啬细节,我可能需要他们来理解。


当前回答

让我们首先了解python GIL提供了什么:

任何操作/指令都在解释器中执行。GIL确保解释器在特定时刻由单个线程持有。你的多线程python程序在一个解释器中工作。在任何特定时刻,这个解释器都由一个线程控制。这意味着只有持有解释器的线程在任何时刻都在运行。

为什么这是个问题呢?

Your machine could be having multiple cores/processors. And multiple cores allow multiple threads to execute simultaneously i.e multiple threads could execute at any particular instant of time.. But since the interpreter is held by a single thread, other threads are not doing anything even though they have access to a core. So, you are not getting any advantage provided by multiple cores because at any instant only a single core, which is the core being used by the thread currently holding the interpreter, is being used. So, your program will take as long to execute as if it were a single threaded program.

然而,潜在的阻塞或长期运行的操作,如I/O、图像处理和NumPy数字运算,发生在GIL之外。从这里拍的。因此,对于这样的操作,尽管存在GIL,多线程操作仍然比单线程操作快。因此,GIL并不总是一个瓶颈。

编辑:GIL是CPython的一个实现细节。IronPython和Jython没有GIL,所以一个真正的多线程程序应该是可能的,虽然我从来没有使用过PyPy和Jython,不确定这一点。

其他回答

我想分享一个书中的例子多线程的视觉效果。这就是典型的死锁情况

static void MyCallback(const Context &context){
Auto<Lock> lock(GetMyMutexFromContext(context));
...
EvalMyPythonString(str); //A function that takes the GIL
...    
}

现在考虑导致死锁的序列中的事件。

╔═══╦════════════════════════════════════════╦══════════════════════════════════════╗
║   ║ Main Thread                            ║ Other Thread                         ║
╠═══╬════════════════════════════════════════╬══════════════════════════════════════╣
║ 1 ║ Python Command acquires GIL            ║ Work started                         ║
║ 2 ║ Computation requested                  ║ MyCallback runs and acquires MyMutex ║
║ 3 ║                                        ║ MyCallback now waits for GIL         ║
║ 4 ║ MyCallback runs and waits for MyMutex  ║ waiting for GIL                      ║
╚═══╩════════════════════════════════════════╩══════════════════════════════════════╝

让我们首先了解python GIL提供了什么:

任何操作/指令都在解释器中执行。GIL确保解释器在特定时刻由单个线程持有。你的多线程python程序在一个解释器中工作。在任何特定时刻,这个解释器都由一个线程控制。这意味着只有持有解释器的线程在任何时刻都在运行。

为什么这是个问题呢?

Your machine could be having multiple cores/processors. And multiple cores allow multiple threads to execute simultaneously i.e multiple threads could execute at any particular instant of time.. But since the interpreter is held by a single thread, other threads are not doing anything even though they have access to a core. So, you are not getting any advantage provided by multiple cores because at any instant only a single core, which is the core being used by the thread currently holding the interpreter, is being used. So, your program will take as long to execute as if it were a single threaded program.

然而,潜在的阻塞或长期运行的操作,如I/O、图像处理和NumPy数字运算,发生在GIL之外。从这里拍的。因此,对于这样的操作,尽管存在GIL,多线程操作仍然比单线程操作快。因此,GIL并不总是一个瓶颈。

编辑:GIL是CPython的一个实现细节。IronPython和Jython没有GIL,所以一个真正的多线程程序应该是可能的,虽然我从来没有使用过PyPy和Jython,不确定这一点。

假设您有多个线程,它们实际上不接触彼此的数据。它们应该尽可能独立地执行。如果你有一个“全局锁”,你需要获取它来(比如说)调用一个函数,这最终会成为一个瓶颈。首先,您可能无法从多线程中获得太多好处。

把它类比到现实世界:想象100个开发人员在一个只有一个咖啡杯的公司工作。大多数开发人员会把时间花在等待咖啡上,而不是编码。

这些都不是Python特有的——我不知道Python最初需要GIL做什么。不过,希望这能让你们更好地理解这个概念。

为什么Python (CPython和其他)使用GIL

从http://wiki.python.org/moin/GlobalInterpreterLock

在CPython中,全局解释器锁(GIL)是一个互斥锁,可以防止多个本机线程同时执行Python字节码。这个锁是必要的,主要是因为CPython的内存管理不是线程安全的。

如何从Python中删除它?

像Lua,也许Python可以启动多个虚拟机,但Python没有这样做,我猜应该有一些其他的原因。

在Numpy或其他一些python扩展库中,有时,将GIL释放给其他线程可以提高整个程序的效率。

当两个线程访问同一个变量时,就有问题了。 例如,在c++中,避免这个问题的方法是定义一些互斥锁,以防止两个线程同时进入一个对象的setter。

多线程在python中是可能的,但是两个线程不能同时执行 粒度比一条python指令还要细。 正在运行的线程正在获得一个名为GIL的全局锁。

这意味着如果你为了利用你的多核处理器而开始编写一些多线程代码,你的性能不会提高。 通常的解决方案包括多进程。

请注意,如果您在用C语言编写的方法中,则有可能释放GIL。

GIL的使用不是Python固有的,而是它的一些解释器,包括最常见的CPython。 (#edited,见评论)

GIL问题在Python 3000中仍然有效。