一、python多線程基礎
python多線程主要涉及兩個類:thread和threading,後者實際是對前者的封裝,由於threading提供了更完善的鎖機制,運用場景更多,重點學習了這個類的使用。
threading.Thread類的使用:
1、在自己的線程類的__init__裏調用threading.Thread.__init__(self, name = threadname),threadname爲線程的名字
2、 run(),通常需要重寫,編寫代碼實現做需要的功能。
3、getName(),獲得線程對象名稱
4、setName(),設置線程對象名稱
5、start(),啓動線程
6、join([timeout]),等待另一線程結束後再運行。
7、setDaemon(bool),設置子線程是否隨主線程一起結束,必須在start()之前調用。默認爲False。
8、isDaemon(),判斷線程是否隨主線程一起結束。
9、isAlive(),檢查線程是否在運行中。
例子如下:
import threading import time #繼承threading.Thread類 class timer(threading.Thread): def __init__(self, num, interval): threading.Thread.__init__(self) self.thread_num = num self.interval = interval self.thread_stop = False #重新run()方法 def run(self): while not self.thread_stop: print 'Thread Object(%d), Time:%s\n' %(self.thread_num, time.ctime()) time.sleep(self.interval) def stop(self): self.thread_stop = True def test(): thread1 = timer(1, 1) thread2 = timer(2, 2) thread1.start() thread2.start() time.sleep(10) thread1.stop() thread2.stop() return if __name__ == '__main__': test()
通常我們通過繼承threading.Thread類後重寫run方法可以實現我們想做的事情,另一種實現多線程的方法是通過threading.Thread類直接生成線程,同時直接指定線程要執行的方法以及方法相應的參數。見以下例子:
import threading def runTest(x,y): for i in range(x,y): print i t1 = threading.Thread(target=runTest,args=(15,20)) t2 = threading.Thread(target=runTest,args=(25,35)) t1.start() t2.start() t1.join() t2.join()
二、線程同步
1、簡單的同步
通過鎖是實現同步最簡單的方式。python的鎖對象由thread.Lock類創建。基本流程如下:
1)線程可以使用鎖的acquire()方法獲得鎖,這樣鎖就進入“locked”狀態;
2)每次只有一個線程可以獲得鎖,如果當另一個線程試圖獲得這個鎖的時候,就會被系統變爲“blocked”狀態;
3)擁有鎖的線程調用鎖的release()方法來釋放鎖,這樣鎖就會進入“unlocked”狀態;
4)“blocked”狀態的線程就會收到一個通知,並有權利獲得鎖。如果多個線程處於“blocked”狀態,所有線程都會先解除“blocked”狀態,然後系統選擇一個線程來獲得鎖,其他的線程繼續沉默(“blocked”)。
這樣一個鎖機制存在的問題是,當一個線程獲得了鎖之後沒有釋放,又申請了同一個鎖資源,此時該線程會進入blocked狀態,而且形成死鎖。threading.RLock鎖原語解決了該問題。RLock對象允許一個線程多次對其進行acquire操作,因爲在其內部通過一個counter變量維護着線程acquire的次數。而且每一次的acquire操作必須有一個release操作與之對應,在所有的release操作完成之後,別的線程才能申請該RLock對象。
import threading mylock = threading.RLock() num=0 class myThread(threading.Thread): def __init__(self, name): threading.Thread.__init__(self) self.t_name = name def run(self): #num作爲共享資源 global num while True: #把共享資源的處理放在acquire()和release()之間 mylock.acquire() print 'Thread(%s) locked, Number: %d\n'%(self.t_name, num) if num>=4: mylock.release() print 'Thread(%s) released, Number: %d\n'%(self.t_name, num) break num+=1 print 'Thread(%s) released, Number: %d\n'%(self.t_name, num) mylock.release() def test(): t1 = myThread('t1') t2 = myThread('t2') t1.start() t2.start() if __name__== '__main__': test()
2、條件同步——生產者和消費者問題
當某些條件下才會出現資源競爭的時候就會涉及條件同步。一個形象一點的例子是,伊利牛奶生產廠家可以生產好多牛奶,並將它們放在多個好又多分店進行銷售,小明可以從任一間好又多分店中購買到牛奶。只有當廠家把牛奶放在某一分店裏,小明纔可以從這間分店中買到牛奶。看一下代碼描述:
import threading import time class Producer(threading.Thread): def __init__(self, t_name): threading.Thread.__init__(self, name=t_name) def run(self): global x con.acquire() if x > 0: con.wait() else: for i in range(5): x=x+1 print "producing..." + str(x) con.notify() print x con.release() class Consumer(threading.Thread): def __init__(self, t_name): threading.Thread.__init__(self, name=t_name) def run(self): global x con.acquire() if x == 0: print 'consumer wait1' con.wait() else: for i in range(5): x=x-1 print "consuming..." + str(x) con.notify() print x con.release() con = threading.Condition() x=0 print 'start consumer' c=Consumer('consumer') print 'start producer' p=Producer('producer') p.start() c.start() p.join() c.join() print x
據說可以用隊列的FIFO特性來實現生產者和消費者問題,後續再學習。
資源來自:http://www.cnblogs.com/tqsummer/archive/2011/01/25/1944771.html