Python GIL:表达式中的所有参与者是否在表达式的持续时间内都增加了ref count? 让我说我有一个简单的C++类: class Widget { public: Widget() : x(1) { } void sleep() { sleep(x); } private: int x; };
Python GIL:表达式中的所有参与者是否在表达式的持续时间内都增加了ref count? 让我说我有一个简单的C++类: class Widget { public: Widget() : x(1) { } void sleep() { sleep(x); } private: int x; };,python,gil,Python,Gil,Widget::sleep阻塞,因此我想释放GIL,以便Python可以做一些其他事情,因此我将Widget::sleep包装在如下函数中: static void pyWidgetSleep(Widget& self) { PyThreadState* state = PyEval_SaveThread(); self.sleep(); PyEval_RestoreThread(state); } BOOST_PYTHON_MODULE(libnative)
Widget::sleep
阻塞,因此我想释放GIL,以便Python可以做一些其他事情,因此我将Widget::sleep
包装在如下函数中:
static void pyWidgetSleep(Widget& self)
{
PyThreadState* state = PyEval_SaveThread();
self.sleep();
PyEval_RestoreThread(state);
}
BOOST_PYTHON_MODULE(libnative)
{
boost::python::class_<Widget>("Widget")
.def("sleep", &pyWidgetSleep);
}
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
为完整起见,绑定代码如下所示:
static void pyWidgetSleep(Widget& self)
{
PyThreadState* state = PyEval_SaveThread();
self.sleep();
PyEval_RestoreThread(state);
}
BOOST_PYTHON_MODULE(libnative)
{
boost::python::class_<Widget>("Widget")
.def("sleep", &pyWidgetSleep);
}
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.foo
中使用时,c.x
的唯一引用是c
,t.start()
后面的行可以方便地删除它。
由于pywidgetleep
释放GIL,del c.x
可能会减少对小部件
实例的最后一次引用,从而导致未定义的行为
我无法在我的机器上实现这一突破,这似乎是一个很好的迹象,表明它能像我预期的那样工作,但引用计数并没有记录到如此清晰的程度 (或者,至少,我似乎找不到它)。CPython的相关部分似乎是
PyEval\u evalcodex
,它似乎将Py\u incremf
应用于所有参数
参与函数调用,但我可能完全不参与该调用。这个问题的答案是肯定的,它是安全的。这是Python中如何调用成员函数的结果。考虑在Python中实现<代码> WITGET < /C> >:
class Widget:
def __init__(self):
self.x = 1
def sleep(self):
os.sleep(self.x)
注意Widget.sleep
的第一个参数是如何self
?在调用期间,引用计数将增加!回想起来似乎很明显