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

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


当前回答

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

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

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

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

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

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

其他回答

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

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

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

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

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's GIL is intended to serialize access to interpreter internals from different threads. On multi-core systems, it means that multiple threads can't effectively make use of multiple cores. (If the GIL didn't lead to this problem, most people wouldn't care about the GIL - it's only being raised as an issue because of the increasing prevalence of multi-core systems.) If you want to understand it in detail, you can view this video or look at this set of slides. It might be too much information, but then you did ask for details :-)

请注意,Python的GIL仅对参考实现CPython来说是真正的问题。Jython和IronPython没有GIL。作为Python开发人员,除非编写C扩展,否则通常不会遇到GIL。C扩展作者需要在扩展阻塞I/O时释放GIL,以便Python进程中的其他线程有机会运行。

Python不允许真正意义上的多线程。它有一个多线程包,但如果你想用多线程来加速你的代码,那么使用它通常不是一个好主意。Python有一个称为全局解释器锁(GIL)的构造。

https://www.youtube.com/watch?v=ph374fJqFPE

GIL确保在任何时间只有一个“线程”可以执行。一个线程获得GIL,做一些工作,然后将GIL传递给下一个线程。这发生得非常快,所以在人眼看来,线程是并行执行的,但实际上它们只是轮流使用相同的CPU内核。所有这些GIL传递都会增加执行开销。这意味着如果你想让你的代码运行得更快,那么使用线程包通常不是一个好主意。

使用Python的线程包是有原因的。如果你想同时运行一些事情,而且效率不是问题,那么它完全可以很方便。或者如果你正在运行需要等待某些东西的代码(比如一些IO),那么它可能很有意义。但是线程库不允许你使用额外的CPU内核。

多线程可以外包给操作系统(通过做多处理),一些外部应用程序调用你的Python代码(例如,Spark或Hadoop),或者一些代码调用你的Python代码(例如:你可以让你的Python代码调用一个C函数来做昂贵的多线程工作)。

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

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

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

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

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

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