2016-03-04 90 views
0

是否可以通過使用多線程模塊從其他正在運行的線程釋放鎖?我正在努力的用例是暫時強制一個線程阻塞並稍後解除阻塞。從另一個線程釋放解釋器鎖/強制另一個線程阻塞

from multiprocessing import Process 
import time 

def loop_forever(): 
    while True: 
     pass 

def pause_evaluation(): 
    #Some code here that will force the other thread to release its GIL 

def resume_evaluation(): 
    #Some code here that will allow other thread to reacquire its GIL 

def kill_evaluation(): 
    global p_1 
    p_1.terminate() 

def control_evaluation(): 
    pause_evaluation() 
    time.sleep(30) 
    resume_evaluation() 
    time.sleep(30) 
    kill_evaluation() 

p_1 = Process(target = loop_forever) 
p_2 = Process(target = control_evaluation) 

p_1.start() 
p_2.start() 
p_1.join() 
p_2.join() 
+0

什麼是'多線程',它來自哪裏?這不是標準的庫模塊。 –

+0

對不起,我的意思是多處理 – btomtom5

+0

好的,所以當你說「線程」時,你的意思是「過程」,對吧? –

回答

1

你不能直接從threadingmultiprocessing做到這一點,因爲GIL釋放的人工管理,需要的東西太多輕鬆地提供最便捷的巨蟒層API的一部分。

如果您願意,您可以創建一個C擴展模塊,並專門管理threadsafety。用於手動創建的C擴展共用圖案是這樣的:

#include "Python.h" 
... 

PyObject *manager_function(PyObject *self, PyObject *args) { 
    ... 
    Py_BEGIN_ALLOW_THREADS 
    // Place threaded C code here. 
    // Disallowed from using Python API functions 
    ... 
    Py_END_ALLOW_THREADS 
    ... 
    return result; 
} 

而在用Cython存在nogil上下文管理器,如described here

我想你一個低成本的解決方案是,調查用Cython cython.parallelnogil選項,因爲它可能不是太難你的代碼移植到用Cython,並簡單地使用cdef的一切,但一個Python的「司機「功能。

正如其他人在評論中指出的那樣,CPython解釋器有幾種決定釋放GIL的方式。最常見的是,在主解釋器循環中處理了一定數量的操作代碼(缺省值爲100,可用sys.setcheckinterval進行調整,可用sys.getcheckinterval查看)後,它將事實上釋放GIL。

此外,當解釋程序識別出正在等待I/O的線程時,它可能會釋放GIL。在那種情況下,即使在GIL'd Python中,您也可以通過普通的舊線程實現併發計算。有些線程會高興地執行解釋器操作碼,而另一個線程正在等待套接字讀取信號或來自某個I/O源的東西。

最終,當I/O線程準備好完成讀操作時,GIL將再次被釋放,程序將停止併發並在多線程間恢復完全同步執行。這一切都發生在幕後,並沒有被程序員明確地管理。

+0

注意:在Python 3.2+中,'set-'和'getcheckinterval'函數不再相關,其中GIL被完全更新(多個CPU綁定線程仍然沒有任何優勢,但與Python 2.x-3不同。1,你不使用1.5內核,並獲得0.75核心價值的工作,平衡會走向GIL爭用開銷)。 – ShadowRanger

+0

的確,這是非常重要的一點。這些函數仍然存在於Python的3個更新版本的'sys'中,但它們並不意味着重寫GIL本身的意思。 – ely

相關問題