0

我有一段代码,其中有一个处理线程和一个监视线程。在处理线程中,我调用了 collections.deque.popleft 函数。我想知道这个函数是否释放 GIL,因为即使处理函数在 popleft 函数上被阻塞,我也想运行我的监视器线程

4

2 回答 2

1

我不会回答这个具体问题,而是回答一个不同的问题:

什么是全局解释器锁 (GIL),它何时会阻止我的程序?

简而言之,GIL 保护解释器的状态不被并发线程破坏。

要了解它的用途,请考虑 的低级实现dict,它在某处有一组键,用于快速查找。当您编写一些代码时:

myDict['foo'] = 'bar'

python 解释器需要调整它的键集合。这可能涉及为附加键腾出更多空间以及将特定键添加到该数组中。

如果多个并发线程正在修改该字典,则一个线程可能会重新分配数组,而另一个线程正在修改它,这可能会导致一些不可预测的、可能是不良行为(来自损坏的数据、段错误或心脏出血,如内存内容泄漏)敏感数据或任意代码执行)

由于这不是您可以在 Python 应用程序级别合理描述或防止的那种状态,因此运行时会竭尽全力防止发生此类问题。它的做法是解释器的某些部分,例如对dict的修改,被一个PyGILState_Ensure()/PyGILState_Release()对包围,这样关键操作总是达到一致的状态。

但是请注意,此锁的范围非常狭窄;它不会试图防止一般的数据竞争,它不会保护您免于编写具有多个线程的程序在一个公共容器(例如 a )中覆盖彼此的工作collections.deque,只是即使您确实编写了这样的程序,它不会导致解释器崩溃,您将始终拥有一个有效的、工作的deque. 您可以添加额外的应用程序锁,queue.Queue以便为您的应用程序提供良好的并发语义。

由于 GIL 保护的每个操作都是解释器状态的变化,它从不阻塞外部事件;由于这些事件不会导致解释器状态发生变化,因此信号条件变量不会破坏内存。


唯一可能遇到问题的是当您有多个未阻塞线程时,因为它们可能都在低级解释器中执行代码,它们将竞争 GIL,并且只有一个线程可以持有它,阻塞其他线程也想做一些计算。

除非您正在编写 C 扩展,否则您可能不需要担心它,并且除非您在 python 中有多个计算绑定线程,否则您也不会受到它的影响。

于 2014-06-04T00:54:57.873 回答
-1

是的——deque是线程安全的(感谢@hemanths)http://docs.python.org/2/library/collections.html#collections.deque

不,因为collections.deque不是线程安全的。使用Queue,或创建自己的deque子类。

于 2014-06-03T22:02:48.843 回答