python多線程一——基礎

進程和線程

進程(Process)是計算機中的程序關于數據集合上的一次活動,是系統進行資源分配和調度的基本單位。簡單的說,進程是正在運行的程序的實例。
一般來說,進程一般由文本區域、數據區域和堆棧組成。文本區域存儲處理器執行的代碼,數據區域存儲變量和進程執行期間使用的動態分配的內存,堆棧則存儲活動過程中調用的指令和本地變量。

線程(Thread)是程序執行流的最小單元,線程只擁有運行所必須的資源,其他的資源和該進程中的其他線程共享。有時也被稱之為輕量級進程(LightWeight Process,LWP)。一般一個進程中都有一個主線程。

各自優缺點:
進程擁有獨立的地址空間和資源,進程間通信IPC比較麻煩,當一個進程崩潰后,不會對其他進程造成影響,故多進程程序比較健壯。但進程間切換耗費的資源比較大,時間較長。
線程由于共享所屬進程的資源,故線程間通信比較簡單。線程所擁有的資源比較少,線程間的切換耗時短。

PIL

說起python和線程,那就不得不說一下PIL了,PIL是全局解釋器鎖(Global Interpreter Lock),該鎖保證同時只能有一個線程運行。
在多線程中,python虛擬機的運行方式如下:

1. 設置GIL
2. 切換進一個線程運行
3. 執行一下一個操作:
 - 指定數量的字節碼指令
 - 線程主動讓出控制權
4. 切換線程
5. 解鎖GIL

對于python來說,GIL會在線程進行I/O調用前被釋放,以便其他的線程運行,這也就是Python更適合做I/O密集型的工作。

python中提供了多個模塊來支持多線程編程,如thread,threading,Queue模塊,其中thread模塊提供了基本的線程和鎖定支持,threading提供了更高級別、功能更全面的線程管理,Queue模塊可以創建隊列數據結構,在多個線程之間進行數據共享。

thread模塊
函數方法 描述
thread模塊函數
start_new_thread(function,args,kwargs=None) 派生一個新的線程
allocate_lock() 分配LockType鎖對象
exit() 退出線程
LockType鎖對象方法
acquire(wait=None) 獲取鎖對象
locked() 是否獲取鎖對象
release() 釋放鎖對象

一般來說thread不常用,原因如下:

  1. thread模塊中所擁有的同步元語只有一個,即LockType,
  2. thread對于進程的進入退出沒有控制,當主線程結束時,所有的其他線程也會強制結束,不會發出警告或清理。
  3. 不支持守護線程
  4. thread所支持的操作很少

在python3中thread模塊被更名為_thread
下面給出一個python3關于_thread的簡單例子:

import _thread
import random
from time import ctime, sleep

def loop(nloop, nsec, lock):
    print('start loop:', nloop, 'nsec:', nsec, 'at:', ctime())
    sleep(nsec)
    print('end loop', nloop, 'done at:', ctime())
    lock.release()

def main():
    print('starting at:', ctime())
    locks = []
    for i in range(2):
        lock = _thread.allocate_lock()
        lock.acquire()
        locks.append(lock)

    for i in range(2):
        _thread.start_new_thread(loop, (i, random.randint(1, 4), locks[i]))

    for i in range(2):
        while locks[i].locked():
            pass

    print('all down at:', ctime())

if __name__ == '__main__':
    main()

在這個例子中,首先通過_thread_allocate_lock()來生成鎖對象,并通過acquire()來獲取鎖,這樣就相當于將鎖鎖上,然后將該鎖傳遞給每個線程中。
線程中操作很簡單,休眠傳遞過來的時間,然后釋放鎖。
在主線程中,不停的去判斷兩個鎖是否鎖住,避免主線程執行完導致兩個線程直接被強制結束。運行的結果如下:

starting at: Thu Sep  7 09:57:36 2017
start loop: 0 nsec: 2 at: Thu Sep  7 09:57:36 2017
start loop: 1 nsec: 4 at: Thu Sep  7 09:57:36 2017
end loop 0 done at: Thu Sep  7 09:57:38 2017
end loop 1 done at: Thu Sep  7 09:57:40 2017
all down at: Thu Sep  7 09:57:40 2017

python多線程就暫時講到這里了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容