먼저 B와 J, E와 G의 더 순진한 일치 검색보다는 B와 E 및 G와 J의 PyGILState_Ensure
/PyGILState_Release
쌍을 일치시켜야합니다. , E 단계는 초기화되지 않은 상태를 해제하여 인터프리터의 내부 상태 정보를 손상시킵니다.)
하지만 문제가없는 단일 상태를 사용하고 있습니다. (나는 이것이 법적 실제로 모르겠지만, 나는 그것이 CPython과의 모든 버전과 안전 확신하고 순서가 일을 얻을 수있는 방법은 확실히 없습니다.)
불행하게도, 이것은이있다 다른 문제입니다. PyGILState_Release
문서가 말하는대로 :
이전에 획득 한 모든 리소스를 해제하십시오. 는 해당 PyGILState_Ensure()
호출하기 전에이었다으로이 호출 후, 파이썬의 상태는 보호하지 않는 한 당신은 (A Release
이후 Ensure
에 걸쳐있는 통역 자원을 수행 할 수없는, 즉
... 동일합니다 물론 바깥 쪽은 Ensure
이지만 실제로는 아무 것도 공개하지 않습니다.)
Release
PyRun_String
으로 보장되는 상태가되면 나머지는 PyRun_String
통화가 무효화됩니다. 중간에 새로 인수 한 국가로 전환하는 것은 도움이되지 않습니다.
는하지만 난 당신이 처음에 Ensure
/Release
불필요하게 남용하는 것 같아요. 인터프리터에 스레드를 등록하고 등록을 취소하고 다시 등록한 다음 다시 등록을 취소 할 필요는 없습니다. 동일한 스레드 내에서 GIL을 릴리스하고 다시 획득하기 만하면됩니다. 그게 Py_BEGIN_ALLOW_THREADS
과 Py_END_ALLOW_THREADS
입니다.
는 PyGILState_Ensure
에 대한 설명서는 말하기를 : 스레드의 상태가 릴리스하기 전에 이전 상태로 복원으로
일반적으로, 다른 스레드 관련 API에서
만큼 PyGILState_Ensure()
및 PyGILState_Release()
호출 사이에 사용할 수있다() . 예를 들어, Py_BEGIN_ALLOW_THREADS
및 Py_END_ALLOW_THREADS
매크로를 정상적으로 사용할 수 있습니다.
그래서 :
PyGILState_STATE state;
B. state = PyGILState_Ensure();
...
E. Py_BEGIN_ALLOW_THREADS
F. Do long-ish processing
G. Py_END_ALLOW_THREADS
...
J. PyGILState_Release(state);
당신이 각 단계에 적절한'PyGILState_STATE'을 사용하고 있는지 있습니까? 즉,'B'에서'E'에있는 것을 전달해야하고,'G'의 값을'J'에 전달하는 다른 변수에 저장해야합니다. (또는'E'와'G'를'Py_BEGIN_ALLOW_THREADS' /'Py_END_ALLOW_THREADS' 쌍으로 만들 수 있습니다.) – abarnert
또한 의사 코드 대신 [SSCCE] (http://sscce.org)를 제공 할 수 있습니까? – abarnert
스레드마다 PyGILState_STATE 값을 사용하고 있으므로 B, E, G 및 J에 대해 동일한 변수가됩니다. – DougN