python多執行緒程式設計1

高洛峰
發布: 2016-10-18 11:43:25
原創
1112 人瀏覽過

多執行緒程式設計必須理解的一些基本概念,適用於所有程式語言。內容:

並發式程式設計

多任務作業系統

多執行緒vs多行程

執行緒

執行緒的生命週期

執行程式

式的類型軟體對並發式程式設計並發送式的視角。並發式程式設計將軟體視為任務和資源的組合-任務之間競爭和共享資源,當資源滿足時執行任務,否則等待資源。

並發式程式設計使得軟體易於理解和重複使用,在某些場景能夠大幅提升效能。

多任務作業系統

要實現並發,首先需要作業系統的支援。現在的作業系統大部分都是多任務作業系統,可以「同時」執行多個任務。

多任務可以在進程或執行緒的層級執行。

進程是指一個記憶體中運行的應用程序,每個進程都有自己獨立的一塊記憶體空間。多任務作業系統可以「並發」執行這些進程。

執行緒是指進程中亂序、多次執行的程式碼區塊,多個執行緒可以「同時」運行,所以認為多個執行緒是「並發」的。多執行緒的目的是為了最大限度的利用CPU資源。例如一個JVM進程中,所有的程式碼都以執行緒的方式運作。

這裡面的「同時」、「並發」只是一種宏觀的感受,實際上從微觀層面看只是進程/線程的輪換執行,只不過切換的時間非常短,所以產生了「並行」的感覺。

多執行緒vs多行程

作業系統會為每個行程分配不同的記憶體區塊,而多個執行緒共享程序的記憶體區塊。這帶來最直接的不同就是創建執行緒的開銷遠小於建立程序的開銷。

同時,由於記憶體區塊不同,所以進程之間的通訊相對困難。需要採用pipe/named pipe,signal, message queue, shared memory,socket等手段;而線程間的通訊簡單快速,就是共享進程內的全域變數。

但是,進程的調度由作業系統負責,執行緒的調度就需要我們自己來考慮,避免死鎖,飢餓,活鎖,資源枯竭等情況的發生,這會增加一定的複雜度。而且,由於線程之間共享內存,我們還需要考慮線程安全性的問題。

線程安全

以為線程間共享進程中的全局變量,所以當其他線程改變了共享的變量時,可能會對本線程產生影響。所謂線程安全的約束是指一個函數被多個並發線程反覆呼叫時,要一直產生正確的結果。要確保線程安全,主要是透過加鎖的方式保證共享變數的正確存取。

比線程安全更嚴格的約束是"可重入性",即函數在一個線程內執行的過程中被暫停,接下來又在另一個線程內被調用,之後在返回原始線程繼續執行。在整個過程中都能保證正確執行。保證可重入性,通常透過製作全域變數的本地拷貝來實現。

線程的生命週期

所謂的xx生命週期,其實就是某物件的包含產生和銷毀的一張狀態圖。線的生命週期如下圖所示:

各狀態的說明如下:

New新建。新建立的執行緒經過初始化後,進入Runnable狀態。

Runnable就緒。等待線程調度。調度後進入運轉狀態。

Running運行。

Blocked阻塞。暫停運行,解除阻塞後進入Runnable狀態重新等待調度。

Dead消亡。執行緒方法執行完畢返回或異常終止。

可能有3種情況從Running進入Blocked:

同步:執行緒中取得同步鎖,但是資源已經被其他執行緒鎖定時,進入Locked狀態,直到該資源可取得(取得的順序由Lock佇列控制)

睡眠:執行緒運行sleep()或join()方法後,執行緒進入Sleeping狀態。差別在於sleep等待固定的時間,而join是等待子執行緒執行完畢。當然join也可以指定一個「超時時間」。從語意上來說,如果兩個執行緒a,b, 在a中呼叫b.join(),相當於合併(join)成一個執行緒。最常見的情況是在主執行緒中join所有的子執行緒。

等待:在執行緒執行wait()方法後,執行緒進入Waiting狀態,等待其他執行緒的通知(notify)。

執行緒的類型

主執行緒:當一個程式啟動時,就有一個行程被作業系統(OS)創建,同時一個執行緒也立刻執行,該執行緒通常叫做程式的主執行緒(Main Thread)。每個行程至少有一個主線程,主線程通常最後關閉。

子線程:在程式中創建的其他線程,相對於主線程來說就是這個主線程的子線程。

守護線程:daemon thread,對線程的一種標識。守護線程為其他線程提供服務,例如JVM的垃圾回收線程。當剩下的全是守護線程時,進程就會退出。

前台線:相對於守護執行緒的其他執行緒稱為前台執行緒。

python對多執行緒的支援

虛擬機層

Python虛擬機器使用GIL(Global Interpreter Lock,全域解釋器鎖定)來互斥執行緒對共享資源的訪問,暫時無法利用多處理器的優勢。

語言層面

在語言層面,Python對多執行緒提供了很好的支持,Python中多執行緒相關的模組包括:thread,threading,Queue。可以方便地支援建立執行緒、互斥鎖、信號量、同步等特性。

thread:多執行緒的底層支援模組,一般不建議使用。

threading:對thread進行了封裝,將一些執行緒的操作物件化,提供下列類別:

Thread 執行緒類別

Timer與Thread類似,但要等待一段時間後才開始執行

Lock 鎖原語

RLock 可重入鎖。讓單執行緒可以再次取得已經取得的鎖定

Condition 條件變量,能讓一個執行緒停下來,等待其他執行緒滿足某個「條件」

Event 通用的條件變數。多個執行緒可以等待某個事件發生,在事件發生後,所有的執行緒都被啟動

Semaphore為等待鎖的執行緒提供一個類似「等候室」的結構

BoundedSemaphore 與semaphore類似,但不允許超過初始值

Queue:實作了多生產者(Producer)、多消費者(Consumer)的佇列,支援鎖原語,能夠在多個執行緒之間提供很好的同步支援。提供的類別:

Queue佇列

LifoQueue後入先出(LIFO)佇列

PriorityQueue 優先佇列

其中Thread類別是你主要的執行緒類,可以建立行程實例。這類提供的函數包括:

getName(self) 傳回執行緒的名字

isAlive(self) 布林標誌,表示這個執行緒是否還在運作中

isDaemon(self) 傳回執行緒的daemon標誌

join(self

join(self

join(self

join(self

join(self

join(self

join(self , timeout=None) 程式掛起,直到執行緒結束,如果給出timeout,則最多阻塞timeout秒

run(self) 定義執行緒的功能函數

setDaemon(self, daemonic)  把執行緒的daemon標誌設為daemonicsetDaemon(self, daemonic)  把執行緒的daemon標誌設為daemonicsetDaemon(self, daemonic)  把執行緒的daemon標誌設為daemonic

setName(self, name) 設定執行緒的名字

start(self) 開始執行緒執行

第三方支援

如果你特別在意效能,還可以考慮一些「微線程」的實作:

Stackless Python: Python的一個增強版本,提供了對微線程的支援。微線程是輕量級的線程,在多個線程間切換所需的時間更多,佔用資源也更少。

greenlet:是 Stackless 的副產品,其將微線程稱為 “tasklet” 。 tasklet運行在偽並發中,使用channel進行同步資料交換。而”greenlet”是更原始的微線程的概念,沒有調度。你可以自己建構微線程的調度器,也可以使用greenlet實現高階的控制流。 🎜🎜下一節,將開始用python建立和啟動執行緒。 🎜🎜🎜🎜
相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!