依賴和死鎖問題

在介紹各種多執行緒開發工具前我先要介紹下多執行緒下最大的二個問題。

第一個問題就是任務執行的依賴關係。在不同執行緒間執行的任務程式碼會有先後次序的需求。但因為多執行緒的特性會導致這些程式碼被同時執行。那麼需要一種方法來控制多執行緒間程式碼的依賴關係。違反這種依賴關係可能會導致資料的丟失。執行過程的嚴重錯誤。甚至崩潰,宕機。

第二個問題就是死鎖。在多執行緒執行過程中,多個執行緒會訪問同一個資料。如果其中一個執行緒鎖住了一個數據,然後請求另一個數據的鎖。而其他執行緒剛好鎖住了他請求中的資料,並也剛好請求他擁有的資料。就會導致兩個執行緒互相等待系統卡死的問題。

為什麼多執行緒下這兩個問題是核心問題?

因為這兩個問題的出現與多執行緒軟體規模成正比,也就是說隨著多執行緒軟體規模的增加,這兩個問題出現的機率也在增加。他們像達克摩斯之劍一樣懸掛在任何多執行緒專案的上空。

POSIX Threads

POSIX Threads的標準文件地址:

POSIX Threads也就是pthread是由IEEE協會在1995制定的C語言執行緒庫標準。也是應用最廣泛的多執行緒標準。這個庫實現了基本的多執行緒程式設計介面。包括執行緒的建立,停止,加入等。也包括了互斥鎖,訊號,執行緒儲存等功能。但windows系統並沒有加入這個標準。其他作業系統對標準的實現也各不相同。但不可否認這是一個使用最廣泛的庫。雖然缺乏一些高階功能如訊息佇列和執行緒安全型別。

多執行緒開發工具的比較

intel TBB

TBB是開源專案其地址為:

多執行緒開發工具的比較

TBB是intel開發針對intel硬體最佳化的多執行緒庫。看相關測試效能和使用pthread相近。這點讓我有點困惑?不過TBB提供了大量高階功能的擴充套件,這點要比pthread強很多。

TBB的高階功能包括任務系統, 多執行緒安全的map, queue, vector等型別。以及parallel_for,parallel_while,parallel_reduce等並行演算法。這些高階功能讓開發並行軟體更加容易。

不過TBB只能使用在intel的硬體上。這侷限了TBB的發展。

可以說TBB和POSIX Threads都是多執行緒開發的基本工具。學習的門檻非常高,需要使用者非常熟悉多執行緒的特性,才能針對不同的應用場景施展工具。這兩款庫是非常棒的多用途工具箱,但需要作為使用者的你是一個老師傅。這兩款多執行緒庫和其他的多執行緒庫一樣都只提供了多執行緒開發的基礎功能,並沒有解決多執行緒依賴和死鎖的問題。

go語言

go是google推出的開發語言其地址為

go goroutine 使用go語言開發多執行緒就非常容易了。只要一句go func()就線上程內啟動了一個任務。

package main

import “fmt”

func main() {

messages := make(chan string)

go func() { messages <- “ping” }()

msg := <-messages

fmt。Println(msg)

}

語法“messages := make(chan string)”則建立了一個訊息佇列用於接受和傳送訊息。 這個接受和傳送訊息也非常的簡單隻要使用關鍵字 “<-messages”和“messages <- ”就可以實現。

go語言幫我們實現了自動的執行緒池和任務分配管理器。 但是GO語言沒有實現對資料的分片和保護。也就是說GO語言透過使用自動的執行緒池, 任務分配管理器, 訊息通訊等方法。有效地解決了多執行緒中任務間依賴的問題。

但沒有解決第二個問題,也就是死鎖問題。這樣導致隨著任務數量的增加,資料鎖的大量使用,死鎖的機率也大幅增加。如果使用GO語言沒有出現死鎖。哪僅僅是因為你的軟體規模還不夠大,或則參與開發的人員不夠多。

多執行緒開發工具的比較

ECS框架

是unity推薦的開源專案。

其專案地址在

ECS將資料劃分為多個entry, 並保證每個entry每次只有一個system可以使用。 這樣就保證不會產生資料的死鎖。但其缺乏消除多執行緒依賴的治理手段。可會導致多個執行緒中傳送次序問題。

例如,兩個任務都依賴一個物品, 當其中一個任務完成銷燬了物品, 記錄在物品上的狀態丟失, 就會導致另一個任務狀態混亂甚至無法執行。

也就是說在一個時間內的updata中一個system如果修改了另一個system的資料。如果因為執行次序的原因在這個時間片內沒有執行。那麼在下個時間片這個資料有可能被刪除或修改導致執行失敗。因為ECS沒有專門針對跨多執行緒的通訊機制。來保留這些有調整依賴關係的資料。

ECS是以資料導向的時間分片機制,這個機制下不需要任何鎖就可以排程多執行緒中的任務。為了偏執的不引入多執行緒鎖,因為沒有鎖就肯定不會有死鎖的問題。所以ECS未來也不可能引入以多執行緒鎖佇列為基礎的訊息通訊機制。所以ECS的邏輯依賴問題是個無解的問題。這樣就導致ECS雖然功能非常強大,但難以駕馭像極了蘇聯暴力美學的地效飛行器。

多執行緒開發工具的比較

pelagia

是開源專案其地址在

pelagia是由surparallel open source推出的開源專案,唯一同時解決依賴和死鎖的lock-free的多執行緒工具。

在前面我簡單的介紹了多執行緒工具的現狀。我們知道依賴和死鎖是多執行緒開發中必須要解決的兩個問題。並不是簡單的因為依賴和死鎖會有機率的出現在多執行緒專案中。而是因為在多執行緒專案中存在指數規模效應的問題。

所謂

指數規模效應

是指假設一個專案有兩個執行緒,如果你新新增一個執行緒,那麼兩個執行緒間發生依賴和死鎖,就有3的2次方即9種可能。如果有99個執行緒,你同樣是新新增一個執行緒,那麼發生依賴和死鎖的可能就變成了100的2次方種可能。也就是說可能發生依賴和死鎖的狀況,隨著開發任務的增加成指數級別的增加。

這樣就導致每開發一個新的執行緒任務就要和其餘的執行緒任務做仔細的檢查。檢查是否可能出現依賴和死鎖。而這種檢查的規模也是程指數增加的。這樣就導致我們開發的多執行緒專案很快就會達到團隊所能承受的極限。

因為

指數規模效應

的存在就必然會有祖傳程式碼拍死老師傅。為了避免老師傅們被祖傳程式碼拍死。pelagia結合訊息通訊和資料分割槽兩個技術,同時解決依賴和死鎖問題,徹底拯救了老師傅。

pelagia目前處於準完成階段。大部分功能已經開發完畢。包括訊息通訊的統計系統,支援多執行緒的日誌系統,多執行緒資料分割槽的儲存系統。其硬碟儲存系統性能略快於redis。

多執行緒開發工具的比較