【发布时间】:2021-07-07 00:27:03
【问题描述】:
来自a similar question's answer:
您应该能够访问 [一个扩展类型的] cdef 成员 [在一个 nogil 块内]...并调用他们标记为 nogil 的 cdef 函数。
但是,cython documentation 不同意:
GIL释放后,任何涉及python对象的操作都必须先重新获取GIL。
我假设“python 对象”包括 cython 扩展类型。这让我认为下面的伪代码是不安全的,因为它包含了在没有 GIL 的情况下修改 python 对象引起的竞争条件:
def function(ExtensionType arg):
with nogil:
# long running task
# modify arg's member
arg = ExtensionType()
function(arg)
# access arg's member
# (alternatively, accessing and modifying the member could be swapped, with the same issue)
我已将其扩展为实际代码以说明我的困惑:
cimport cytime
cdef class Tester:
cdef int val
def get_val(self):
return self.val
def set_val(self):
print("1: GIL acquired by set_val")
with nogil:
cytime.sleep(0.1) # give me the GIL later, I'm not ready for it yet
self.val = 1
print("3: GIL reacquired by set_val")
t = Tester()
t.set_val()
print("2: val should be 0, but actually is: " + str(t.get_val()))
我预计程序的执行如下:1、2、3。但是,这是输出:
1: GIL acquired by set_val
3: GIL reacquired by set_val
2: val should be 0, but actually is: 1
谁能解释一下?谢谢。
【问题讨论】:
-
val应该是 1 吧?因为那是你设置的。它是安全的(......我会给出一个答案,希望稍后能说明为什么......)。但我认为您真的对 GIL 的作用感到困惑
标签: cython