python多線程基礎

一、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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章