python多線程一——基礎(chǔ)

進程和線程

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

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

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

PIL

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

1. 設(shè)置GIL
2. 切換進一個線程運行
3. 執(zhí)行一下一個操作:
 - 指定數(shù)量的字節(jié)碼指令
 - 線程主動讓出控制權(quán)
4. 切換線程
5. 解鎖GIL

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

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

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

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

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

在python3中thread模塊被更名為_thread
下面給出一個python3關(guān)于_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()來獲取鎖,這樣就相當(dāng)于將鎖鎖上,然后將該鎖傳遞給每個線程中。
線程中操作很簡單,休眠傳遞過來的時間,然后釋放鎖。
在主線程中,不停的去判斷兩個鎖是否鎖住,避免主線程執(zhí)行完導(dǎo)致兩個線程直接被強制結(jié)束。運行的結(jié)果如下:

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多線程就暫時講到這里了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容