綜述
??? 多線程是程序設(shè)計中的一個重要方面,尤其是在服務(wù)器Deamon程序方面。無論何種系統(tǒng),線程調(diào)度的開銷都比傳統(tǒng)的進(jìn)程要快得多。
? Python可以方便地支持多線程。可以快速創(chuàng)建線程、互斥鎖、信號量等等元素,支持線程讀寫同步互斥。美中不足的是,Python的運行在Python 虛擬機(jī)上,創(chuàng)建的多線程可能是虛擬的線程,需要由Python虛擬機(jī)來輪詢調(diào)度,這大大降低了Python多線程的可用性。希望高版本的Python可以 解決這個問題,發(fā)揮多CPU的最大效率。
? 網(wǎng)上有些朋友說要獲得真正多CPU的好處,有兩種方法:
? 1.可以創(chuàng)建多個進(jìn)程而不是線程,進(jìn)程數(shù)和cpu一樣多。
? 2.使用Jython 或 IronPython,可以得到真正的多線程。
? 閑話少說,下面看看Python如何建立線程
? Python線程創(chuàng)建
? 使用threading模塊的 Thread類
? 類接口如下
?需要關(guān)注的參數(shù)是target和args. target 是需要子線程運行的目標(biāo)函數(shù),args是函數(shù)的參數(shù),以tuple的形式傳遞。
? 以下代碼創(chuàng)建一個指向函數(shù)worker 的子線程
???? ...
th = threading.Thread(target=worker,args=(i,acc) ) ;
啟動這個線程
等待線程返回
或者th.join()
如果你可以對要處理的數(shù)據(jù)進(jìn)行很好的劃分,而且線程之間無須通信,那么你可以使用:創(chuàng)建=》運行=》回收的方式編寫你的多線程程序。但是如果線程之間需要訪問共同的對象,則需要引入互斥鎖或者信號量對資源進(jìn)行互斥訪問。
?下面講講如何創(chuàng)建互斥鎖
創(chuàng)建鎖
? ....
使用鎖 ?
????
??????? #鎖定,從下一句代碼到釋放前互斥訪問
??????? g_mutex.acquire()
??????? a_account.deposite(1)
??????? #釋放
??????? g_mutex.release()
最后,模擬一個公交地鐵IC卡繳車費的多線程程序
? 有10個讀卡器,每個讀卡器收費器每次扣除用戶一塊錢進(jìn)入總賬中,每讀卡器每天一共被刷10000000次。賬戶原有100塊。所以最后的總賬應(yīng)該為10000100。先不使用互斥鎖來進(jìn)行鎖定(注釋掉了鎖定代碼),看看后果如何。
import time,datetime import threading def worker(a_tid,a_account): global g_mutex print("Str " , a_tid, datetime.datetime.now() ) for i in range(1000000): #g_mutex.acquire() a_account.deposite(1) #g_mutex.release() print("End " , a_tid , datetime.datetime.now() ) class Account: def __init__ (self, a_base ): self.m_amount=a_base def deposite(self,a_amount): self.m_amount+=a_amount def withdraw(self,a_amount): self.m_amount-=a_amount if __name__ == "__main__": global g_mutex count = 0 dstart = datetime.datetime.now() print("Main Thread Start At: ", dstart) #init thread_pool thread_pool = [] #init mutex g_mutex = threading.Lock() # init thread items acc = Account(100) for i in range(10): th = threading.Thread(target=worker,args=(i,acc) ) ; thread_pool.append(th) # start threads one by one for i in range(10): thread_pool[i].start() #collect all threads for i in range(10): threading.Thread.join(thread_pool[i]) dend = datetime.datetime.now() print("count=", acc.m_amount) print("Main Thread End at: ", dend, " time span ", dend-dstart)
注意,先不用互斥鎖進(jìn)行臨界段訪問控制,運行結(jié)果如下:
從結(jié)果看到,程序確實是多線程運行的。但是由于沒有對對象Account進(jìn)行互斥訪問,所以結(jié)果是錯誤的,只有3434612,比原預(yù)計少了很多。
這次可以看到,結(jié)果正確了。運行時間比不進(jìn)行互斥多了很多,不過這也是同步的代價。
同時發(fā)現(xiàn),寫多線程,多進(jìn)程類的程序,不能用自帶的idle來運行。會有錯誤。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
