Python多線程 簡明例子

來源:互聯網
上載者:User

綜述

    多線程是程式設計中的一個重要方面,尤其是在伺服器Deamon程式方面。無論何種系統,線程調度的開銷都比傳統的進程要快得多。 
Python可以方便地支援多線程。可以快速建立線程、互斥鎖、訊號量等等元素,支援線程讀寫同步互斥。美中不足的是,Python的運行在Python
虛擬機器上,建立的多線程可能是虛擬線程,需要由Python虛擬機器來輪詢調度,這大大降低了Python多線程的可用性。希望高版本的Python可以
解決這個問題,發揮多CPU的最大效率。  網上有些朋友說要獲得真正多CPU的好處,有兩種方法:  1.可以建立多個進程而不是線程,進程數和cpu一樣多。
  2.使用Jython 或 IronPython,可以得到真正的多線程。   閑話少說,下面看看Python如何建立線程    Python線程建立
   
使用threading模組的 Thread類  類介面如下  class
Thread( group=None, target=None, name=None, args=(), kwargs={})    需要關注的參數是target和args. target 是需要子線程啟動並執行目標函數,args是函數的參數,以tuple的形式傳遞。  以下代碼建立一個指向函數worker 的子線程
def worker(a_tid,a_account):

    ...


th = threading.Thread(target=worker,args=(i,acc) ) ;   啟動這個線程
th.start()   等待線程返回
threading.Thread.join(th)

或者th.join()   如果你可以對要處理的資料進行很好的劃分,而且線程之間無須通訊,那麼你可以使用:建立=》運行=》回收的方式編寫你的多線程程式。但是如果線程之間需要訪問共同的對象,則需要引入互斥鎖或者訊號量對資源進行互斥訪問。   下面講講如何建立互斥鎖 建立鎖


g_mutex = threading.Lock()


....
使用鎖



    for
... :

        #鎖定,從下一句代碼到釋放前互斥訪問

        g_mutex.acquire()

        a_account.deposite(1)

        #釋放

        g_mutex.release()   最後,類比一個公交地鐵IC卡繳車費的多線程程式  有10個讀卡機,每個讀卡機收費器每次扣除使用者一塊錢進入總賬中,每讀卡機每天一共被刷10000000次。賬戶原有100塊。所以最後的總賬應該為10000100。先不使用互斥鎖來進行鎖定(注釋掉了鎖定代碼),看看後果如何。 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;   注意,先不用互斥鎖進行臨界段存取控制,運行結果如下: Main Thread Start At:    2009-01-13 00:17:55.296000
Str    0 2009-01-13 00:17:55.312000
Str    1 2009-01-13 00:17:55.453000
Str    2 2009-01-13 00:17:55.484000
Str    3 2009-01-13 00:17:55.531000
Str    4 2009-01-13 00:17:55.562000
Str    5 2009-01-13 00:17:55.609000
Str    6 2009-01-13 00:17:55.640000
Str    7 2009-01-13 00:17:55.687000
Str    8 2009-01-13 00:17:55.718000
Str    9 2009-01-13 00:17:55.781000
End    0 2009-01-13 00:18:06.250000
End    1 2009-01-13 00:18:07.500000
End    4 2009-01-13 00:18:07.531000
End    2 2009-01-13 00:18:07.562000
End    3 2009-01-13 00:18:07.593000
End    9 2009-01-13 00:18:07.609000
End    7 2009-01-13 00:18:07.640000
End    8 2009-01-13 00:18:07.671000
End    5 2009-01-13 00:18:07.687000
End    6 2009-01-13 00:18:07.718000
count= 3434612
Main Thread End at:    2009-01-13 00:18:07.718000    time span    0:00:12.422000   從結果看到,程式確實是多線程啟動並執行。但是由於沒有對對象Account進行互斥訪問,所以結果是錯誤的,只有3434612,比原預計少了很多。   把上面陰影部分代碼的注釋開啟,運行結果如下Main Thread Start At:    2009-01-13 00:26:12.156000
Str    0 2009-01-13 00:26:12.156000
Str    1 2009-01-13 00:26:12.390000
Str    2 2009-01-13 00:26:12.437000
Str    3 2009-01-13 00:26:12.468000
Str    4 2009-01-13 00:26:12.515000
Str    5 2009-01-13 00:26:12.562000
Str    6 2009-01-13 00:26:12.593000
Str    7 2009-01-13 00:26:12.640000
Str    8 2009-01-13 00:26:12.671000
Str    9 2009-01-13 00:26:12.718000
End    0 2009-01-13 00:27:01.781000
End    1 2009-01-13 00:27:05.890000
End    5 2009-01-13 00:27:06.046000
End    7 2009-01-13 00:27:06.078000
End    4 2009-01-13 00:27:06.109000
End    2 2009-01-13 00:27:06.140000
End    6 2009-01-13 00:27:06.156000
End    8 2009-01-13 00:27:06.187000
End    3 2009-01-13 00:27:06.203000
End    9 2009-01-13 00:27:06.234000
count= 10000100
Main Thread End at:    2009-01-13 00:27:06.234000    time span    0:00:54.078000   這次可以看到,結果正確了。已耗用時間比不進行互斥多了很多,需要花54秒才能運行(我機器爛,沒錢更新,呵呵),不過這也是同步的代價,沒辦法。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.