2012-09-14 22 views
7

से पायथन कोड को कॉल करना मैं बहुत उलझन में हूं कि मैं सी (या सी ++) थ्रेड से पायथन कोड को कॉल करते समय थ्रेड-सुरक्षा को कैसे सुनिश्चित कर सकता हूं। इस stackoverflow answer के रूप में ज्यादा पुष्टि करने के लिए लगता है,सी थ्रेड

PyGILState_STATE gstate; 
gstate = PyGILState_Ensure(); 

/* Perform Python actions here. */ 
result = CallSomeFunction(); 
/* evaluate result or handle exception */ 

/* Release the thread. No Python API allowed beyond this point. */ 
PyGILState_Release(gstate); 

और वास्तव में:

Python documentation कह जा सकता है कि ऐसा करने के लिए हमेशा की तरह मुहावरा है लगता है। लेकिन एक टिप्पणीकार (एक बहुत ही उच्च प्रतिष्ठा के साथ) अन्यथा कहते हैं। टिप्पणीकर्ता का कहना है कि आपको PyEval_RestoreThread()/PyEval_SaveThread() का उपयोग करना चाहिए।

डॉक्स इस बात की पुष्टि करने लगते हैं:

PyThreadState* PyEval_SaveThread() 

Release the global interpreter lock (if it has been created and 
thread support is enabled) and reset the thread state to NULL, 
returning the previous thread state (which is not NULL). If the lock 
has been created, the current thread must have acquired it. (This 
function is available even when thread support is disabled at compile 
time.) 

void PyEval_RestoreThread(PyThreadState *tstate) 

Acquire the global interpreter lock (if it has been created and thread 
support is enabled) and set the thread state to tstate, which must not 
be NULL. If the lock has been created, the current thread must not have 
acquired it, otherwise deadlock ensues. (This function is available even 
when thread support is disabled at compile time.) 

रास्ता डॉक्स इस का वर्णन है, ऐसा लगता है कि PyEval_RestoreThread()/PyEval_SaveThread() मूल रूप से एक म्युटेक्स लॉक/अनलॉक मुहावरा है। तो यह समझ में आता है कि सी से किसी भी पायथन कोड को कॉल करने से पहले, आपको पहले जीआईएल को लॉक करने की आवश्यकता है, और उसके बाद इसे अनलॉक करें।

तो यह कौन सा है? जब सी से अजगर कोड बुला, मैं का उपयोग करना चाहिए:

PyGILState_Ensure()/PyGILState_Release()

या

PyEval_RestoreThread/PyEval_SaveThread?


और वास्तव में क्या अंतर है?

उत्तर

6

सबसे पहले, आप लगभग PyEval_RestoreThread/PyEval_SaveThread पर कॉल नहीं करना चाहते हैं। इसके बजाय, आप रैपर मैक्रोज़ Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS पर कॉल करना चाहते हैं। documentation उन मैक्रोज़ के लिए लिखा गया है, यही कारण है कि आप इसे नहीं ढूंढ पाए।

वैसे भी, आप जीआईएल प्राप्त करने के लिए थ्रेड फ़ंक्शंस/मैक्रोज़ का उपयोग नहीं करते हैं; जब आप इसे हासिल कर लेते हैं तो आप उन्हें अस्थायी रूप से जीआईएल जारी करने के लिए उपयोग करते हैं।

तो, आप कभी ऐसा क्यों करना चाहते हैं? खैर, साधारण मामलों में आप नहीं करते हैं; आपको बस Ensure/Release की आवश्यकता है। लेकिन कभी-कभी आपको बाद में अपने पायथन थ्रेड स्टेटस पर पकड़ने की आवश्यकता होती है, लेकिन जीआईएल पर पकड़ने की आवश्यकता नहीं होती है (या को स्पष्ट रूप से जीआईएल पर पकड़ने की आवश्यकता नहीं है, ताकि कुछ अन्य थ्रेड प्रगति हो सकें ताकि यह आपको संकेत दे सके)। जैसे-जैसे दस्तावेज़ों की व्याख्या होती है, इसके लिए सबसे आम कारण फ़ाइल I/O या व्यापक CPU-bound गणना कर रहे हैं।

अंत में, क्या कोई ऐसा मामला है जहां आप मैक्रोज़ के बजाय फ़ंक्शन को कॉल करना चाहते हैं? हां, अगर आप stashed PyThreadState तक पहुंच चाहते हैं। यदि आप किसी कारण के बारे में नहीं सोच सकते हैं कि आप इसे क्यों चाहते हैं, तो आपके पास शायद कोई नहीं है।