国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Python多線程和Python的鎖

2019-11-14 17:35:39
字體:
來源:轉載
供稿:網友

Python多線程 
Python中實現多線程有兩種方式,一種基于_thread模塊(在Python2.x版本中為thread模塊,沒有下劃線)的start_new_thread()函數,另一種基于threading模塊的Thread類。 
其實Python的多線程編程不能真正利用多核的CPU,但是用開源模塊使你的計算壓力分布到多核CPU上......... 

一.使用start_new_thread()實現線程,是比較底層的實現方式,所有線程共享他們global數據,為了達到同步,模塊也提供了簡單的鎖機制 

_thread.start_new_thread(function, args[, kwargs])
啟動一個新的進程,并返回其標識符. 線程執行的函數需要的參數由args(必須為一個元組)提供,亦可通過可選參數kwargs提供關鍵字參數組  成的字典。當函數返回時,啟動的線程也   停止退出。如果函數中存在未處理異常,會打印堆棧跟蹤后線程停止退出(其他線程繼續執行)。


其中線程標識符是一個非0整數,并沒有直接意思,可以當作從一個線程組成的特殊字典中索引本線程的一個key,也可用_thread.get_ident()得到,在線程退出后,標識符會被系統回收。在線程執行過程中可以調用_thread.exit()終止本線程的執行。 

java代碼  收藏代碼
  1. import _thread  
  2. import time  
  3. def threadFunction(count):  
  4.     for i in range(count):  
  5.       PRint('進程id為%d的打印%d'%(_thread.get_ident(),i))  
  6.       i-=1  
  7.       time.sleep(0.1)  
  8.   
  9. def begin():  
  10.   ident1=_thread.start_new_thread(threadFunction,(100,))  
  11.   print('啟動標識符為%d的進程'%(ident1,))  
  12.   ident2=_thread.start_new_thread(threadFunction,(100,))  
  13.   print('啟動標識符為%d的進程'%(ident2,))  
  14.   
  15.    
  16. if __name__ == '__main__':  
  17.   begin()  




二.使用Thread類來實現多線程,這種方式是對_thread模塊(如果沒有_thread,則為dummy_threading)的高級封裝,在這種方式下我們需創建新類繼承threading.Thread,和java一樣重寫threading.Thread的run方法即可.啟動線程用線程的start方法,它會調用我們重寫的run方法. 

Java代碼  收藏代碼
  1. class MyThread(threading.Thread):  
  2.     '''只能重寫__init__ 和 run 兩個方法'''  
  3.     def __init__(self,name):  
  4.         threading.Thread.__init__(self)  
  5.         self.name=name  
  6.         self.bool_stop=False  
  7.     def run(self):  
  8.         while not self.bool_stop:  
  9.             print('進程%s,于%s'%(self.name,time.asctime()))  
  10.             time.sleep(1)  
  11.     def stop(self):  
  12.         self.bool_stop = True  
  13.   
  14.   
  15. if __name__ == '__main__':  
  16.     th1=MyThread('one')  
  17.     th2=MyThread('two')  
  18.     th1.start()  
  19.     th2.start()  




Thread類還定義了以下常用方法與屬性: 

Thread.getName() /Thread.setName()
老方式用于獲取和設置線程的名稱,官方建議用Thread.name替代
Thread.ident
獲取線程的標識符。只有在調用start()方法執行后才有效,否則返回None。
Thread.is_alive()
判斷線程是否是激活的。
Thread.join([timeout])
調用Thread.join將會使主調線程堵塞,直到被調用線程運行結束或超時。參數timeout是一個數值類型,表示超時時間,如果未提供該參數,那么主調線程將一直堵塞到被調線程結束。



Python中的鎖 

先用_thread模塊的Lock鎖來實現生產者消費者問題,Lock對象是Python提供的低級線程控制工具,使用起來非常簡單,只需下面3條語句即可: 

_thread.allocate_lock()返回一個新Lock對象,即為一個新鎖
lock.acquire() 相當于P操作,得到一個鎖,
lock.release()相當于V操作,釋放一個鎖


代碼如下: 

Java代碼  收藏代碼
  1. import _thread,time,random  
  2. dish=0  
  3. lock = _thread.allocate_lock()  
  4. def producerFunction():  
  5.    '''如果投的篩子比0.2大,則向盤子中增加一個蘋果'''  
  6.    global lock,dish  
  7.    while True:  
  8.        if(random.random() > 0.1):  
  9.          lock.acquire()  
  10.          if dish < 100:  
  11.            dish+=1  
  12.            print('生產者增加了一個蘋果,現在有%d個蘋果'%(dish,))  
  13.          lock.release()  
  14.          time.sleep(random.random()*3)  
  15.   
  16. def consumerFunction():  
  17.   '''如果投的篩子比0.5大,則從盤子中取一個蘋果'''  
  18.   global lock,dish  
  19.   while True:  
  20.     if(random.random() > 0.9):  
  21.       lock.acquire()  
  22.       if dish > 0:  
  23.         dish-=1  
  24.         print('消費者拿走一個蘋果現,在有%d個蘋果'%(dish,))  
  25.       lock.release()  
  26.       time.sleep(random.random()*3)  
  27.   
  28. def begin():  
  29.   ident1=_thread.start_new_thread(producerFunction,())  
  30.   ident2=_thread.start_new_thread(consumerFunction,())   
  31. if __name__ == '__main__':  
  32.   begin()  


另一個較高級的鎖為RLock鎖,RLock對象內部維護著一個Lock對象,它是一種可重入的對象。對于Lock對象而言,如果一個線程連續兩次進行acquire操作,那么由于第一次acquire之后沒有release,第二次acquire將掛起線程。這會導致Lock對象永遠不會release,使得線程死鎖。RLock對象允許一個線程多次對其進行acquire操作,因為在其內部通過一個counter變量維護著線程acquire的次數。而且每一次的acquire操作必須有一個release操作與之對應,在所有的release操作完成之后,別的線程才能申請該RLock對象。 


threading模塊對Lock也提供和封裝,提供了更高級的同步方式(可以理解為更高級的鎖),包括threading.Event和threading.Condition,其中threading.Event為提供了簡單的同步方式:一個進程標記event,其他進程等待,只需下面的幾個方法即可: 

Event.wait([timeout])
堵塞線程,直到Event對象內部標識位被設為True或超時(如果提供了參數timeout)。
Event.set()
將標識號設為Ture
Event.clear()
設為標識符False



threading.Condition 可以把Condiftion理解為一把高級的瑣,它提供了比Lock, RLock更高級的功能,允許我們能夠控制復雜的線程同步問題。threadiong.Condition在內部維護一個瑣對象(默認是RLock),可以在創建Condigtion對象的時候把瑣對象作為參數傳入。Condition也提供了acquire, release方法,其含義與瑣的acquire, release方法一致,其實它只是簡單的調用內部瑣對象的對應的方法而已。Condition還提供了如下方法(特別要注意:這些方法只有在占用瑣(acquire)之后才能調用,否則將會報RuntimeError異常。): 

Condition.wait([timeout]):    
wait方法釋放內部所占用的瑣,同時線程被掛起,直至接收到通知被喚醒或超時(如果提供了timeout參數的話)。當線程被喚醒并重新占有瑣的時候,程序才會繼續執行下去。
Condition.notify():  
喚醒一個掛起的線程(如果存在掛起的線程)。注意:notify()方法不會釋放所占用的瑣。
Condition.notify_all()
喚醒所有掛起的線程(如果存在掛起的線程)。注意:這些方法不會釋放所占用的瑣。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 濮阳县| 贡觉县| 房产| 电白县| 安仁县| 枣阳市| 运城市| 油尖旺区| 聊城市| 嘉鱼县| 边坝县| 丹阳市| 黄龙县| 体育| 吉隆县| 夏津县| 米脂县| 金湖县| 育儿| 衡阳县| 吴忠市| 兴业县| 沧源| 荣昌县| 绥化市| 铜鼓县| 盐源县| 正宁县| 馆陶县| 营口市| 昆山市| 太仆寺旗| 靖宇县| 万山特区| 古丈县| 无锡市| 阳西县| 萨嘎县| 资源县| 灵宝市| 万源市|