目錄
五、總結
在 linux 系統中,當多個執行緒並行執行時,如果需要訪問同乙個資源,那麼在訪問資源的地方,需要使用作業系統為我們提供的同步原語來進行保護。同步原語包括:互斥鎖、條件變數、訊號量等,被保護的**稱作「臨界區」。
這是非常正規的流程,我們基本上也都是這麼做的。
那有沒有想過,這些同步原語對**的執行效率會產生多大的影響?是否可以不使用作業系統提供的這些機制,而是用其它純軟體的方法也能達到保護臨界區的目的呢?
這篇文章我們介紹一下 peterson(皮特森)演算法,也許實用性不強,但是可以給我們帶來一些思考,提高我們的程式設計元技能。
這個演算法主要用來解決臨界區的保護問題。我們知道,乙個臨界區必須保證 3 個條件:
互斥訪問: 在任意乙個時刻,最多只能有乙個執行緒可以進入臨界區;peterson演算法是乙個實現互斥鎖的併發程式設計演算法,可以控制兩個執行緒訪問乙個共享的使用者資源而不發生訪問衝突。空閒讓進:當沒有執行緒正在執行臨界區的**時,必須在所有申請進入臨界區的執行緒中,選擇其中的乙個,讓它進入臨界區;
有限等待:當乙個執行緒申請進去臨界區時,不能無限的等待,必須在有限的時間內獲得許可進入臨界區。也就是說,不論其優先順序多低,不應該餓死在該臨界區入口處。
peterson 演算法是基於雙線程互斥訪問的 lockone 與 locktwo 演算法而來。
lockone 演算法使用乙個 flag 布林陣列這 2 個演算法都實現了互斥,但是都存在死鎖的可能。peterson 演算法把這兩種演算法結合起來,完美地用軟體實現了雙線程互斥問題。locktwo 使用乙個 turn 的整型量
演算法說明如下
兩個重要的全域性變數:
flag 陣列:有 2 個布林元素,分別代表乙個執行緒是否申請進入臨界區;turn:如果 2 個執行緒都申請進入臨界區,這個變數將會決定讓哪乙個執行緒進入臨界區;
// 被 2 個執行緒同時訪問的全域性資源
static int num = 0;
bool flag[2] = ;
int turn = 0;
void *thread0_routine(void *arg)
return null;
}void *thread1_routine(void *arg)
return null;
}
全域性資源 num 的初始值為0 ,兩個程式設計分別遞增 100 萬次,因此最終結果應該是200 萬,實際測試結果也確實如此。
1. 單執行緒中:mutex 互斥鎖對**執行效率的影響
for (int i = 0; i < 1000000; ++i)
以上**,耗時約:1.8ms -- 3.5ms。
for (int i = 0; i < 1000000; ++i)
以上**,耗時約:23.9ms -- 38.9ms。可以看出,上鎖和解鎖對**執行效率的影響還是很明顯的。
2. 多執行緒中:mutex 互斥鎖對**執行效率的影響
void *thread0_routine(void *arg)
return null;
}void *thread1_routine(void *arg)
return null;
}
耗時:
thread0: diff = 125.8ms3. 在兩個執行緒中,使用 peterson 演算法來保護臨界區thread1: diff = 129.1ms
耗時:
thread1: diff = 1.89mspeterson 演算法使用純軟體來保護臨界區,比使用作業系統提供的互斥鎖表現出了更好的效能。thread0: diff = 1.94ms
但是它也有乙個缺點:只能使用在2 個執行緒中,但是由於它與平台無關,在某些特殊的場合,也許能夠拿來為我們所用!
好文章,要**;越分享,越幸運!
推薦閱讀
【c 語言】
1. c語言指標-從底層原理到花式技巧,用**和**幫你講解透徹
2. 原來gdb的底層除錯原理這麼簡單
3. 一步步分析-如何用c實現物件導向程式設計
4. 提高**逼格的利器:巨集定義-從入門到放棄
5. 利用c語言中的setjmp和longjmp,來實現異常捕獲和協程
【應用程式設計】
1. 都說軟體架構要分層、分模組,具體應該怎麼做(一)
2. 都說軟體架構要分層、分模組,具體應該怎麼做(二)
3. 物聯網閘道器開發:基於mqtt訊息匯流排的設計過程(上)
4. 物聯網閘道器開發:基於mqtt訊息匯流排的設計過程(下)
5. 我最喜歡的程序之間通訊方式-訊息匯流排
【作業系統】
1. 為什麼太空飛行器、飛彈喜歡用微控制器,而不是嵌入式系統?
【物聯網】
1. 關於加密、證書的那些事
2. 深入lua指令碼語言,讓你徹底明白除錯原理
【胡說八道】
1. 以我失敗的職業經歷:給初入職場的技術人員幾個小建議
C邊角料4 C基礎之自製靜態庫,動態庫
c基礎之自製靜態庫,動態庫 前言 c基礎文章 發布版本包含.a檔案和.h標頭檔案。c檔案不會給別人 我們選擇寫乙個makefile,這樣可以將編譯的過程記錄下來。all gcc richard.c o richard.o c ar rc librichard.a richard.o 1 第一步 自己...
用C語言得到Linux本機的IP位址2
include include include include include include include include define maxinte ces 16 main argc,argv register int argc register char argv else jugde w...
用2的冪次方表示正整數(C語言)
任何乙個正整數都可以用2的冪次方表示。例如 137 27 23 2 0 同時約定冪次方用括號來表示,即ab 可表示為a b 由此可知,137可表示為 2 7 2 3 2 0 進一步 7 22 2 20 21用2表示 3 2 2 0 所以最後137可表示為 2 2 2 2 2 0 2 2 2 0 2 ...