一、全局鎖
1、在Python中,Python代碼的執行由Python虛擬機來控制,而在Python虛擬機中,同一時刻只有一個線程在執行,就像單CPU的系統中運行多個進程那樣,內存中可以存放多個程序,但在任意時刻,只有一個程序在CPU中運行。同樣的,在Python解釋器中可以“運行”多個線程,但在任意時刻,只有一個線程在Python解釋器中運行。
2、對Python虛擬機的訪問由全局解釋器鎖【GIL】來控制,正是這個鎖能保證同一時刻只有一個線程在運行。
3、多線程環境中,Python虛擬機的執行方式為:
1. 設置GIL 2. 切換到一個線程去運行 3. 運行: a. 指定數量的字節碼指令,或者 b. 線程主動讓出控制(可以調用time.sleep(0)) 4. 把線程設置為睡眠狀態 5. 解鎖GIL 6. 再次重復以上所有步驟 |
二、線程模塊
Python提供了【thread】和【threading】模塊。在多線程編程中,建議使用【threading】模塊,這是因為:
1、在【thread】模塊中,當主線程退出時,其他沒有被清除的線程沒有運行結束就會被退出。但在【threading】模塊中能確保所有的“重要的”子線程(這里的重要的子線程指的是守護線程)運行結束后,進程才會結束
2、在【threading】模塊是更高級的線程模塊,它不僅提供了Thread類,還提供了線程同步機制
thread模塊
內建函數
1、thread.start_new_thread(function, args[, kwargs=None]) 這個函數用來啟動一個線程,其參數含義分別為: function:線程任務函數 args:線程任務函數的參數【以元組的方式傳入】 kwargs:可選的參數 2、thread.interrupt_main() 這個函數用來中斷主線程 3、thread.exit() 這個函數用來退出線程 4、thread.get_ident() 這個函數用來獲取線程標識號 5、thread.allocate_lock() 這個線程用來獲取LockType對象 6、thread.stack_size([size]) 這個線程用來返回創建新線程棧容量,其參數含義為: size:指定創建新線程棧容量,該參數取值為0或不小於32,768(32KB) |
LockType對象
1、lock.acquire([waitflag]) 這個函數用來申請鎖對象,若是獲得鎖對象返回True,否則返回False 2、lock.release() 這個函數用來釋放鎖對象【使用該函數前提是獲取鎖對象】 3、lock.locked() 這個函數用來獲取對象鎖的狀態,若是已被鎖住則返回True,否則返回False |
示例:
>>> import thread >>> sum = 0 /*****************線程任務函數**********************/ >>> def add(lock): global sum #設置為全局變量 lock.acquire() #加鎖 i = 1 while(i < 3): sum = sum + 10 i = i + 1 id = thread.get_ident() #線程號 print "Thread ",id,"set sum = ",sum lock.release() #釋放鎖 /***********************啟動線程**************************/ >>> def startTask(): lock = thread.allocate_lock() #申請鎖對象 task_0 = thread.start_new_thread(add,(lock,)) task_1 = thread.start_new_thread(add,(lock,)) /************************測試**************************/ >>> startTask() >>> Thread 764 set sum = 20 Thread 5240 set sum = 40
threading模塊
【threading】模塊式以【thread】為基礎,但提供更高的線程類以及同步機制。
內建函數
1、threading.activeCount() 這個函數用來獲取【active Thread】的數目 2、threading.enumerate() 這個函數用來獲取【active Thread】列表。注意:包括中斷的線程以及還未開始的線程 3、threading.currentThread() 這個函數用來獲取當前運行的【Thread object】 4、threading.settrace(func) 這個函數用來設置所有通過【threading】模塊啟動的線程的跟蹤函數,該函數在【Thread Object】的【run】方法執行前被調用,其參數含義為: func:跟蹤函數名 5、threading.setprofile(func) 這個函數用來設置所有通過【threading】模塊啟動的線程的profile函數 6、threading.Event() 這個工廠函數用來獲取一個新的【Event Object】 7、threading.Lock() 這個工廠函數用來獲取【LockType Object】 8、threading.RLock() 這個工廠函數用來獲取【RLock Object】 9、threading.Condition() 這個工廠函數用來獲取【Condition Object】 10、threading.Semaphore([value]) 這個工廠函數用來獲取【Semaphore Object】 11、threading.BoundedSemaphore([value]) 這個工廠函數用來獲取【Bounded Semaphore Object】 |
內建類
1、class threading.local 類似Java的ThreadLocal 2、class threading.Thread(group=None, target=None, name=None, args=(), kwargs={}) 構造函數參數含義如下: target:Thread類中【run】函數調用的函數 name:指定線程的名,默認線程名格式為:【Thread-N】 args:target函數的參數 1)、start() 啟動線程,值得注意的是:該方法只能被線程調用一次,否則拋出異常RuntimeError 2)、run() 線程任務函數。常被子類重寫,類似Java Thread類的run函數 3)、is_alive() 判斷線程是否【alive】 4)、setDaemon() 將線程設置為守護線程 3、class threading.Timer(interval, function, args=[], kwargs={}) Timer類繼承threading.Thread類,其參數含義為: interval:線程時間執行時間間隔,以秒為單位 function:Thread類中run函數執行的目標函數 args:目標函數的參數 1)、cancel() 取消Timer任務的執行 |
示例
/***************************Timer實例************************/ >>> def putOutNumber(): id = threading.currentThread().getName() print id,'Hello' >>> def startTimer(): timer = threading.Timer(60,putOutNumber) timer.start() >>> startTimer() >>> Thread-1 Hello /****************繼承Thread與Semaphore實例********************/ >>> import threading >>> class MyThread(threading.Thread): def __init__(self,name,semaphore): threading.Thread.__init__(self,None,None,name,None) self.semaphore = semaphore def run(self): #override run function self.semaphore.acquire() i = 1 while(i < 3): print self.getName(),' print ',i i = i + 1 self.semaphore.release() >>> def startTask(): semaphore = threading.Semaphore() thread_0 = MyThread("Thread_0",semaphore) thread_1 = MyThread("Thread_1",semaphore) thread_0.start() thread_1.start() >>> startTask() >>> Thread_0 print 1 Thread_0 print 2 Thread_1 print 1 Thread_1 print 2 /*********************進程之間進行通信************************/ >>> class ManagerThread(threading.Thread): def __init__(self,name,event): threading.Thread.__init__(self,None,None,name,None) self.event = event def run(self): #override run function print self.getName(),' say ','go' self.event.set() >>> class PeopleThread(threading.Thread): def __init__(self,name,event): threading.Thread.__init__(self,None,None,name,None) self.event = event def run(self): self.event.wait() print self.getName(),' start ','go' >>> def startTask(): event = threading.Event() m_thread = ManagerThread("Manager",event) p_thread = PeopleThread("People",event) p_thread.start() m_thread.start() /*************************測試****************************/ >>> startTask() >>> Manager say go People start go
Mutex
內建類
1、class mutex.mutex mutex對象有兩個屬性:鎖和隊列。當鎖沒有被鎖時,隊列是空的。 /*********************mutex Object 函數********************/ 1)、mutex.test() 這個函數檢測mutex是否被鎖 2)、 mutex.testandset() 這個函數用來檢測mutex是否被鎖,若是沒有鎖住,則鎖住並返回True,否則返回False。值得注意的是:這個函數是原子操作 3)、mutex.lock(function, argument) 這個函數用來執行函數function(argument)【前提是mutex沒有被鎖】。如果mutex鎖被鎖,則將function(argument)放入隊列中 4)、mutex.unlock() 這個函數用來解鎖mutex【前提是隊列是空的】。如果隊列不是空的,則在隊列中取出第一個function(argument)執行並不解鎖 |
示例
>>> import mutex >>> def putOutTask(text): print text >>> def startTask(): m_metux = mutex.mutex() m_metux.lock(putOutTask,'I am task_0') m_metux.lock(putOutTask,'T am task_1') m_metux.lock(putOutTask,'I am task_2') m_metux.lock(putOutTask,'T am task_3') m_metux.lock(putOutTask,'I am task_4') m_metux.lock(putOutTask,'T am task_5') while(m_metux.test()): m_metux.unlock() m_metux.unlock() /**************************測試***************************/ >>> startTask() I am task_0 T am task_1 I am task_2 T am task_3 I am task_4 T am task_5