gpt4 book ai didi

python GIL : Do all participants in an expression have ref count incremented for the duration of the expression?

转载 作者:太空宇宙 更新时间:2023-11-04 06:34:36 25 4
gpt4 key购买 nike

假设我有一个简单的 C++ 类:

class Widget
{
public:
Widget() :
x(1)
{ }

void sleep()
{
sleep(x);
}

private:
int x;
};

Widget::sleep block ,所以我想释放 GIL 以便 Python 可以做一些其他的事情,所以我将 Widget::sleep 包装在一个像这样的功能:

static void pyWidgetSleep(Widget& self)
{
PyThreadState* state = PyEval_SaveThread();
self.sleep();
PyEval_RestoreThread(state);
}

为了完整起见,绑定(bind)代码如下所示:

BOOST_PYTHON_MODULE(libnative)
{
boost::python::class_<Widget>("Widget")
.def("sleep", &pyWidgetSleep);
}

我有一个简单的 Python 脚本,如下所示:

import libnative
import threading

class C:
def __init__(self):
self.x = libnative.Widget()
self.sleeping = False

def foo(self):
self.sleeping = True
self.x.sleep()

c = C()
t = threading.Thread(target=c.foo)
t.start()
while not c.sleeping:
pass
del c.x

表达式中的所有参与者是否都在表达式持续时间内增加了他们的引用计数?c.xC.foo 中使用时唯一引用的是 ct.start() 之后的行> 随手删除。由于 pyWidgetSleep 释放 GIL,del c.x 可能会减少对 Widget 实例的最后引用,从而导致未定义的行为。


我无法在我的机器上进行此中断,这似乎很好地表明它按我预期的方式工作,但引用计数并未记录到如此清晰的程度(或者,至少,我似乎找不到它)。 CPython 的相关部分似乎是 PyEval_EvalCodeEx,它看起来像是将 Py_INCREF 应用于所有参数涉及一个函数调用,但我可能完全不关心那个。

最佳答案

这个问题的答案是是的,它是安全的。这是由于在 Python 中调用成员函数的方式造成的。考虑是否 Widget 是用 Python 实现的:

class Widget:
def __init__(self):
self.x = 1

def sleep(self):
os.sleep(self.x)

注意 Widget.sleep 的第一个参数是 self 吗?引用计数在调用期间递增!回想起来似乎很明显......

关于 python GIL : Do all participants in an expression have ref count incremented for the duration of the expression?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12945457/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com