多執行緒互斥鎖訪問演算法(下)------Lamport演算法(麵包店演算法)
你好!這裡是風箏的部落格,
歡迎和我一起交流。
Lamport麵包店演算法是解決多個執行緒併發訪問一個共享的單使用者資源的互斥問題的演算法。 由Leslie Lamport發明。
Lamport把這個併發控制演算法可以非常直觀地類比為顧客去麵包店採購:
已知有n位顧客要進入麵包店採購,安排他們按照次序在前臺登記一個簽到號碼。該簽到號碼逐次加1。
根據簽到號碼的由小到大的順序依次入店購貨。
完成購買的顧客在前臺把其簽到號碼歸0. 如果完成購買的顧客要再次進店購買,就必須重新排隊。
同時進入麵包店採購的兩個或兩個以上的顧客有可能得到相同的號碼。
多個顧客如果抓到相同的號碼, 則規定按照顧客名字的字典次序進行排序, 這裡假定顧客是沒有重名的。
在計算機系統中, 顧客就相當於執行緒,每個程式有一個唯一的標識,而入店購貨就是進入臨界區獨佔訪問該共享資源。由於計算機實現的特點,存在兩個執行緒獲得相同的簽到號碼的情況,這是因為兩個執行緒幾乎同時申請排隊的簽到號碼,這兩個執行緒讀到的號碼是完全一樣的。所以,該演算法規定如果兩個執行緒的排隊簽到號碼相等,則執行緒id號較小的具有優先權。
我在看一些文章時,發現有如下描述:
為了方便,定義如下符號:若a<c或a==c和b<d同時成立,(a,b)<(c,d)
但是我看了產生歧義,看了好一會才理解,應該這樣寫才好:
若a<c或( a==c和b<d同時成立 ),即:(a < c) || ((a == c) && (b < d)),表示為(a,b)<(c,d)
這樣就好理解多了。
核心程式碼如下:
#define true 1
#define false 0
#define process_num 4//執行緒數目
int choosing[process_num]={false};
int number[process_num]={0};
int find_max(void)/*找出最大號碼*/
{
int max=0;
int i=0;
for(;i<process_num;++i)
{
if(number[i]>max)
max=number[i];
}
return max;
}
void enter_lock(int thread_id)
{
int i=0;
choosing[thread_id]=true;
number[thread_id]=find_max()+1;/*選號碼*/
choosing[thread_id]=false;
for(;i<process_num;++i)
{
while(choosing[i]);/*等待其他執行緒選號碼*/
while((number[i] != 0)&&
( (number[i] < number[thread_id]) || ((number[i] == number[thread_id]) && (i < thread_id)) ));/*阻塞,等待排程*/
}
}
void exit_lock(int thread_id)
{
number[thread_id]=0;/*釋放號碼*/
}
這就是lamport的核心演算法,當我們需要訪問臨界區(互斥資源)時:
void process_A(void)//執行緒0
{
enter_lock(1);
//臨界區
//訪問資源
exit_lock(1);
}
void process_B(void)//執行緒1
{
enter_lock(2);
//臨界區
//訪問資源
exit_lock(2);
}
我們可以舉例模擬一下:
有兩個執行緒A(thread_id=1)和B(thread_id=2),
情況一:
當執行緒A進入enter_lock(1);,選取的號碼為1(number[1]=1),此時,無其他執行緒佔用資源。
for迴圈遍歷時,i=1時,對應的是執行緒A的資料,第二個while不成立,執行緒A得到資源時。
情況二:
當執行緒A進入enter_lock(1);,選取的號碼為1(number[1]=1),此時,系統排程,執行緒B執行,執行緒B得到的號碼為2(number[2]=2)。
for迴圈遍歷時,i=1時,對應的是執行緒A的資料,第二個while為:
while((number[1] != 0)&&( (number[1] < number[2]) || ((number[1] == number[2]) && (1 < 2)) ));
可知,while條件成立,則阻塞,待執行緒A釋放資源時,才得以執行。
情況三:
當執行緒B進入enter_lock(2);,選取的號碼為1(number[2]=1),此時,系統排程,執行緒A執行,執行緒A得到的號碼為2(number[1]=2)。
for迴圈遍歷時,i=2時,對應的是執行緒B的資料,第二個while為:
while((number[2] != 0)&&( (number[2] < number[1]) || ((number[2] == number[1]) && (2 < 1)) ));
可知,while條件成立,則阻塞,待執行緒B釋放資源時,才得以執行。
這樣,每個執行緒只寫它自己的choosing[thread_id]、number[thread_id],只讀取其它執行緒的這兩個資料項。
這個演算法不需要基於硬體的原子(atomic)操作實現,即它可以純軟體實現。
解決了peterson演算法的侷限,使得多個執行緒能參與互斥競爭。
多執行緒互斥鎖訪問演算法(上)——Peterson演算法
相關文章
- 多執行緒互斥鎖訪問演算法(上)------Peterson演算法執行緒演算法
- 多執行緒(2)-執行緒同步互斥鎖Mutex執行緒Mutex
- 執行緒同步與互斥:互斥鎖執行緒
- 執行緒的互斥鎖執行緒
- Linux多執行緒的使用一:互斥鎖Linux執行緒
- 畫江湖之 PHP 多執行緒開發 【執行緒安全 互斥鎖】PHP執行緒
- 畫江湖之 PHP 多執行緒開發 [執行緒安全 互斥鎖]PHP執行緒
- “生命遊戲”的多執行緒演算法思考遊戲執行緒演算法
- python多執行緒程式設計3: 使用互斥鎖同步執行緒Python執行緒程式設計
- Linux之執行緒互斥鎖Linux執行緒
- linux程式多執行緒互斥鎖的簡單使用Linux執行緒
- 執行緒安全: 互斥鎖和自旋鎖(10種)執行緒
- 多執行緒鎖的問題執行緒
- windows多執行緒同步--互斥量Windows執行緒
- 演算法:互斥集合演算法
- Java多執行緒中執行緒安全與鎖問題Java執行緒
- 多執行緒_鎖執行緒
- Java多執行緒—執行緒同步(單訊號量互斥)Java執行緒
- 多執行緒之8鎖問題執行緒
- C++11多執行緒程式設計(二)——互斥鎖mutex用法C++執行緒程式設計Mutex
- windows多執行緒同步互斥--總結Windows執行緒
- Java多執行緒(2)執行緒鎖Java執行緒
- Java多執行緒/併發12、多執行緒訪問static變數Java執行緒變數
- Linux Qt使用POSIX多執行緒條件變數、互斥鎖(量)LinuxQT執行緒變數
- Java 多執行緒併發程式設計之互斥鎖 Reentrant LockJava執行緒程式設計
- .NET 固定時間視窗演算法實現(無鎖執行緒安全)演算法執行緒
- 執行緒安全佇列(使用互斥鎖進行實現)執行緒佇列
- iOS多執行緒安全-13種執行緒鎖?iOS執行緒
- 多執行緒-死鎖問題概述和使用執行緒
- java多執行緒–同步鎖Java執行緒
- Java多執行緒-無鎖Java執行緒
- 求多邊形凸包(線性演算法)--陳氏凸包演算法--演算法
- C#多執行緒學習(六) 互斥物件C#執行緒物件
- C# 多執行緒學習(6) :互斥物件C#執行緒物件
- Gil全域性解釋鎖和執行緒互斥鎖的關係執行緒
- JAVA(二)異常/包及訪問許可權/多執行緒/泛型Java訪問許可權執行緒泛型
- 演算法題---五個執行緒排序輸出演算法執行緒排序
- linux多執行緒-----同步機制(互斥量、讀寫鎖、條件變數)Linux執行緒變數