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

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

python中的多線程【轉】

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

轉載自: http://c4fun.cn/blog/2014/05/06/python-threading/

python中關于多線程的操作可以使用thread和threading模塊來實現,其中thread模塊在Py3中已經改名為_thread,不再推薦使用。而threading模塊是在thread之上進行了封裝,也是推薦使用的多線程模塊,本文主要基于threading模塊進行介紹。在某些版本中thread模塊可能不存在,要使用dump_threading來代替threading模塊。

線程創建

threading模塊中每個線程都是一個Thread對象,創建一個線程有兩種方式,一種是將函數傳遞到Thread對象中執行,另一種是從Thread繼承,然后重寫run方法(是不是跟java很像)。

下面使用這兩種方法分別創建一個線程并同時執行

 1 import random, threading 2 def threadFunction(): 3     for i in range(10): 4         PRint 'ThreadFuction - %d'%i 5         time.sleep(random.randrange(0,2)) 6  7  8 class ThreadClass(threading.Thread): 9     def __init__(self):10         threading.Thread.__init__(self);11         12     def run(self):13         for i in range(10):14             print 'ThreadClass - %d'%i15             time.sleep(random.randrange(0,2))16 17 if __name__ == '__main__':18     tFunc = threading.Thread(target = threadFunction);19     tCls  = ThreadClass()20     tFunc.start()21     tCls.start()

執行結果如下,可以看到兩個線程在交替打印。至于空行和一行多個輸出,是因為Py的print并不是線程安全的,在當前線程的print打印了部分內容后,準備打印換行之前,被別的線程中的print搶先,在換行之前打印了其它的內容。

ThreadFuction - 0ThreadFuction - 1ThreadFuction - 2ThreadClass - 0ThreadFuction - 3ThreadClass - 1ThreadFuction - 4ThreadClass - 2ThreadClass - 3ThreadClass - 4ThreadFuction - 5ThreadClass - 5ThreadClass - 6ThreadClass - 7ThreadClass - 8ThreadFuction - 6ThreadClass - 9ThreadFuction - 7ThreadFuction - 8ThreadFuction - 9

Thread類的構造函數定義如下

class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})group: 留作ThreadGroup擴展使用,一般沒什么用target:新線程的任務函數名name:  線程名,一般也沒什么用args:  tuple參數kwargs:dictionary參數

Thread類的成員變量和函數如下

start()         啟動一個線程run()           線程執行體,也是一般要重寫的內容join([timeout]) 等待線程結束name            線程名ident           線程IDdaemon          是否守護線程isAlive()、is_alive()    線程是否存活getName()、setName()     Name的get&set方法isDaemon()、setDaemon()  daemon的get&set方法

這里的守護線程與linux中的守護進程并不是一個概念。這里是指當所有守護線程退出后主程序才會退出,否則即使線程任務沒有結束,只要不是守護線程,都會跟著主程序一起退出。而Linux中的守護進程定義正好相反,守護進程已經脫離父進程,不會隨著父進程的結束而退出。

線程同步

線程同步是多線程中的一個核心問題,threading模塊對線程同步有著良好的支持、包括線程特定數據、信號量、互斥鎖、條件變量等。

線程特定數據

簡而言之,線程特定數據就是線程獨自持有的全局變量,相互之間的修改不會造成影響。

threading模塊中使用local()方法生成一個線程獨立對象,舉例如下,其中sleep(1)是為了保證讓子線程先運行完再運行接下來的語句。

 1 data = threading.local() 2 def threadFunction(): 3     global data 4     data.x = 3 5     print threading.currentThread(), data.x 6      7 if __name__ == '__main__': 8     data.x = 1 9     tFunc = threading.Thread(target = threadFunction).start();10     time.sleep(1)11     print threading.current_thread(), data.x

<Thread(Thread-1, started 36208)> 3<_MainThread(MainThread, started 35888)> 1

輸出如上,可以看到,Thread-1中對data.x的修改并沒有影響到主線程中data.x的值。

互斥鎖

threading中定義了兩種鎖:threading.Lock和threading.RLock。兩者的不同在于后者是可重入鎖,也就是說在一個線程內重復LOCK同一個鎖不會發生死鎖,這與POSIX中的PTHREAD_MUTEX_RECURSIVE也就是可遞歸鎖的概念是相同的。

關于互斥鎖的API很簡單,只有三個函數————分配鎖,上鎖,解鎖。

threading.Lock()        分配一個互斥鎖acquire([blocking=1])   上鎖(阻塞或者非阻塞,非阻塞時相當于try_lock,通過返回False表示已經被其它線程鎖住。)release()               解鎖

下面通過一個例子來說明互斥鎖的使用。在之前的例子中,多線程print會造成混亂的輸出,這里使用一個互斥鎖,來保證每行一定只有一個輸出。

 1 def threadFunction(arg): 2     while True: 3         lock.acquire() 4         print 'ThreadFuction - %d'%arg 5         lock.release() 6  7 if __name__ == '__main__': 8     lock = threading.Lock() 9     threading.Thread(target = threadFunction, args=(1,)).start();10     threading.Thread(target = threadFunction, args=(2,)).start();

條件變量

條件變量總是與互斥鎖一起使用的,threading中的條件變量默認綁定了一個RLock,也可以在初始化條件變量的時候傳進去一個自己定義的鎖。

可用的函數如下

threading.Condition([lock])  分配一個條件變量acquire(*args)               條件變量上鎖release()                    條件變量解鎖wait([timeout])              等待喚醒,timeout表示超時notify(n=1)                  喚醒最大n個等待的線程notifyAll()、notify_all()    喚醒所有等待的線程

下面這個例子使用條件變量來控制兩個線程交替運行

 1 num = 0 2 def threadFunction(arg): 3     global num 4     while num < 10: 5         cond.acquire() 6         while num % 2 != arg: 7             cond.wait() 8         print 'Thread %d - %d' %(arg, num) 9         num += 110         cond.notify()11         cond.release()12 13 if __name__ == '__main__':14     cond = threading.Condition()15     threading.Thread(target = threadFunction, args=(0,)).start();16     threading.Thread(target = threadFunction, args=(1,)).start();

輸出如下

Thread 0 - 0Thread 1 - 1Thread 0 - 2Thread 1 - 3Thread 0 - 4Thread 1 - 5Thread 0 - 6Thread 1 - 7Thread 0 - 8Thread 1 - 9Thread 0 - 10

其實上面這個程序是有問題的,我們想打印的是0~9,但實際上10也被打印了出來,原因很簡單,因為兩個線程交替打印,使得num在一個線程中可能加2,從而導致10被打印出來,所以必須在打印前再次check。


上一篇:GetWord3.3屏幕取詞

下一篇:ctypes調用dll

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 铜川市| 临朐县| 竹溪县| 洮南市| 德昌县| 岳西县| 乐东| 宿松县| 龙海市| 航空| 龙山县| 石阡县| 喜德县| 文昌市| 新蔡县| 建瓯市| 黔西县| 定州市| 宜川县| 南召县| 彭水| 青田县| 黔东| 宁安市| 颍上县| 青浦区| 德阳市| 洛浦县| 都兰县| 城步| 化德县| 保德县| 恭城| 洪湖市| 云林县| 黄冈市| 波密县| 呼玛县| 卢龙县| 乌鲁木齐市| 定州市|