我正在为我的Python应用程序编写一个C++扩展。我理解Python是用来防止多个线程同时访问PyObject的。但是,我的问题是我的扩展代码是单线程的,我还需要获得GIL吗?
假设在Python应用程序中有一些代码,如
import time
from threading import Thread
COUNT = 50000000
def countdown(n):
while n>0:
n -= 1
t1 = Thread(target=countdown, args=(COUNT//2,))
t2 = Thread(target=countdown, args=(COUNT//2,))
start = time.time()
t1.start()
t2.start()
t1.join()
t2.join()
end = time.time()
print('Time taken in seconds -', end - start)
我知道,即使有两个线程,它们也不会因为GIL而并行执行。如果我在两个线程中调用了我的c++扩展,并且我的c++扩展是单线程的,那该怎么办?我需要考虑吉尔吗?
或者另一个问题,我假设线程将尝试在python代码中保持GIL。如果它离开Python并执行c++代码,GIL会被释放吗?
发布于 2019-08-05 21:42:11
我想我们在谈论的是CPython,它是吉尔。
该实现保证在解释器将控制权转移到C++扩展时保持GIL。这意味着您可以自由地调用解释器,检查任何对象等;任何其他需要访问解释器的线程都保证在尝试获取GIL时被阻塞。这也意味着您的C++扩展不需要来考虑GIL,如果它不关心访问解释器的线程的话。
这种“安全第一”方法的缺点是,在执行扩展的代码时,实现会阻止对解释器的所有访问。如果您的扩展代码不需要访问解释器--例如,因为它可以在本地副本/缓冲区上工作,或者在IO上即将被阻塞--那么您应该立即释放GIL,以便其他线程能够运行,并在返回到解释器之前重新获取它。
考虑让两个Python线程尝试用新的工作调用您的扩展。第一个线程将被调度,阻塞解释器,调用您的分机并等待它返回。当它返回时,解释器切换到第二个线程,只有这样,该线程才能调用您的扩展。现在,它必须等待,阻塞线程1。实际上,并发线程永远不会并行运行。从扩展中释放GIL允许其他线程取得进展。但它并不要求程序是正确的。
https://stackoverflow.com/questions/57366067
复制相似问题