摘要:序面包店算法是解決多個(gè)線程并發(fā)訪問(wèn)一個(gè)共享的單用戶資源的互斥問(wèn)題的算法。面包店一次只能接待一位顧客的采購(gòu)。已知有位顧客要進(jìn)入面包店采購(gòu),按照次序安排他們?cè)谇芭_(tái)登記一個(gè)簽到號(hào)碼。顧客根據(jù)簽到號(hào)碼的由小到大的順序依次入店購(gòu)貨。
序
Lamport面包店算法是解決多個(gè)線程并發(fā)訪問(wèn)一個(gè)共享的單用戶資源的互斥問(wèn)題的算法。由萊斯利·蘭波特發(fā)明。
算法類比Lamport把這個(gè)并發(fā)控制算法非常直觀地類比為顧客去面包店采購(gòu)。
面包店一次只能接待一位顧客的采購(gòu)。
已知有n位顧客要進(jìn)入面包店采購(gòu),按照次序安排他們?cè)谇芭_(tái)登記一個(gè)簽到號(hào)碼。該簽到號(hào)碼逐次增加1。
顧客根據(jù)簽到號(hào)碼的由小到大的順序依次入店購(gòu)貨。
完成購(gòu)買的顧客在前臺(tái)把其簽到號(hào)碼歸0。如果完成購(gòu)買的顧客要再次進(jìn)店購(gòu)買,就必須重新排隊(duì)。
這個(gè)類比中的顧客就相當(dāng)于線程,而入店購(gòu)貨就是進(jìn)入臨界區(qū)獨(dú)占訪問(wèn)該共享資源。由于計(jì)算機(jī)實(shí)現(xiàn)的特點(diǎn),存在兩個(gè)線程獲得相同的簽到號(hào)碼的情況,這是因?yàn)閮蓚€(gè)線程幾乎同時(shí)申請(qǐng)排隊(duì)的簽到號(hào)碼,讀取已經(jīng)發(fā)出去的簽到號(hào)碼情況,這兩個(gè)線程讀到的數(shù)據(jù)是完全一樣的,然后各自在讀到的數(shù)據(jù)上找到最大值,再加1作為自己的排隊(duì)簽到號(hào)碼。
為此,該算法規(guī)定如果兩個(gè)線程的排隊(duì)簽到號(hào)碼相等,則線程id號(hào)較小的具有優(yōu)先權(quán)。
原理Lamport時(shí)間戳原理如下:
每個(gè)事件對(duì)應(yīng)一個(gè)Lamport時(shí)間戳,初始值為0
如果事件在節(jié)點(diǎn)內(nèi)發(fā)生,時(shí)間戳加1
如果事件屬于發(fā)送事件,時(shí)間戳加1并在消息中帶上該時(shí)間戳
如果事件屬于接收事件,時(shí)間戳 = Max(本地時(shí)間戳,消息中的時(shí)間戳) + 1
5個(gè)原則為了請(qǐng)求資源,進(jìn)程A發(fā)送消息(Tm:A)給所有的其他進(jìn)程,并且把這個(gè)消息放到進(jìn)程隊(duì)列中,Tm是消息的時(shí)間戳
當(dāng)進(jìn)程B接收到了進(jìn)程A的(Tm:A)請(qǐng)求后,會(huì)把它放到自己的請(qǐng)求隊(duì)列,然后發(fā)送一個(gè)帶時(shí)間戳的確認(rèn)消息給A
為了釋放資源,進(jìn)程A移除所有(Tm:A)的請(qǐng)求消息,然后發(fā)送帶時(shí)間戳的A釋放資源請(qǐng)求消息給其他所有的進(jìn)程
當(dāng)進(jìn)程B接收到進(jìn)程A釋放資源的請(qǐng)求,它會(huì)移除隊(duì)列中任意的(Tm:A)的資源請(qǐng)求
當(dāng)滿足以下兩個(gè)條件時(shí),進(jìn)程A會(huì)被分配該資源:
a)有一個(gè)(Tm:A)的請(qǐng)求,按照=>關(guān)系排在隊(duì)列第一位;
b)A接收到了一個(gè)時(shí)間戳大于Tm的來(lái)自所有其他進(jìn)程的消息
代碼示例private void processRevcMsg(Message m) throws InterruptedException { // 原理4 如果事件屬于接收事件,時(shí)間戳 = Max(本地時(shí)間戳,消息中的時(shí)間戳) + 1 clock.update(m.getTimestamp()); lastSendMap.put(m.getFrom(), m); switch (m.getMsgType()) { case REQUEST_RES: // rule 2 當(dāng)進(jìn)程B接收到了進(jìn)程A的(Tm:A)請(qǐng)求后,會(huì)把它放到自己的請(qǐng)求隊(duì)列,然后發(fā)送一個(gè)帶時(shí)間戳的確認(rèn)消息給A addMessageToReqMap(m); Message ackMsg = new Message(pid, m.getMsgId(), MessageType.REQUEST_ACK, clock.time()); // send ack to sender sendToTargetProcess(ackMsg,m.getFrom()); break; case REQUEST_ACK: break; case RELEASE_RES: // rule 4 當(dāng)進(jìn)程B接收到進(jìn)程A釋放資源的請(qǐng)求,它會(huì)移除隊(duì)列中任意的(Tm:A)的資源請(qǐng)求 dropMessageFromReqMap(m); break; default: break; } tryToAcquireResource(); } private void tryToAcquireResource() { synchronized (reqMap) { if(!reqMap.containsKey(pid) || reqMap.get(pid).isEmpty()){ return ; } Message myMessage = reqMap.get(pid).get(0); int acceptCount = 1; // rule 5 當(dāng)滿足以下兩個(gè)條件時(shí),進(jìn)程A會(huì)被分配該資源:a)有一個(gè)(Tm:A)的請(qǐng)求,按照=>關(guān)系排在隊(duì)列第一位;b)A接收到了一個(gè)時(shí)間戳大于Tm的來(lái)自所有其他進(jìn)程的消息 // condition (ii) of rule 5 // A接收到了一個(gè)來(lái)自所有其他進(jìn)程的消息,而且時(shí)間戳大于Tm for (Map.Entrydocentry : lastSendMap.entrySet()) { if (entry.getKey() == pid) { continue; } if (isFirstEarlier(myMessage, entry.getValue())) { acceptCount++; }else{ return ; } } if (!coordinator.hasAcceptedAll(acceptCount)){ return; } // condition (i) of rule 5 // 有一個(gè)Tm:A的請(qǐng)求,按照=>關(guān)系排在隊(duì)列第一位 for (Map.Entry > entry : reqMap.entrySet()) { if (entry.getKey() != pid && !entry.getValue().isEmpty()) { if (!isFirstEarlier(myMessage, entry.getValue().get(0))) { return; } } } // remove this request message final Message firstMsg = reqMap.get(pid).remove(0); workingPool.execute(new Runnable() { public void run() { coordinator.acquire(firstMsg.getMsgId(), pid, firstMsg.getTimestamp()); // emulate owning resources for a long time try { Thread.sleep(50L); // rule 3 為了釋放資源,進(jìn)程A移除所有(Tm:A)的請(qǐng)求消息,然后發(fā)送帶時(shí)間戳的A釋放資源請(qǐng)求消息給其他所有的進(jìn)程程 coordinator.release(firstMsg.getMsgId(), pid, firstMsg.getTimestamp()); Message releaseMsg = new Message(pid, firstMsg.getMsgId(),MessageType.RELEASE_RES, clock.time()); sendToOtherProcesses(releaseMsg); } catch (InterruptedException e) { e.printStackTrace(); } } }); } }
Lamport面包店算法
分布式系統(tǒng)理論基礎(chǔ) - 時(shí)間、時(shí)鐘和事件順序
分布式系統(tǒng)時(shí)序基礎(chǔ)
lamport
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/70377.html
摘要:在這種狀態(tài)下,拜占庭將軍們才能保證有多于支軍隊(duì)在同一時(shí)間一起發(fā)起進(jìn)攻,從而贏取戰(zhàn)斗拜占庭將軍問(wèn)題中并不去考慮通信兵是否會(huì)被截獲或無(wú)法傳達(dá)信息等問(wèn)題,即消息傳遞的信道絕無(wú)問(wèn)題。共識(shí)算法的核心就是解決拜占庭將軍問(wèn)題分布式網(wǎng)絡(luò)一致性問(wèn)題。 本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接:什么是拜占庭將軍問(wèn)題原文已更新,請(qǐng)讀者前往原文閱讀 接觸區(qū)塊鏈的同學(xué),多少都聽(tīng)說(shuō)過(guò)拜占庭將軍問(wèn)題,經(jīng)??吹交蚵?tīng)到某某...
摘要:摘要前文數(shù)據(jù)挖掘與機(jī)器學(xué)習(xí)技術(shù)入門實(shí)戰(zhàn)與大家分享了分類算法,在本文中將為大家介紹聚類算法和關(guān)聯(lián)分析問(wèn)題。比如,聚類算法可以實(shí)現(xiàn)公司客戶價(jià)值自動(dòng)劃分,網(wǎng)頁(yè)自動(dòng)歸類等。 摘要:前文數(shù)據(jù)挖掘與機(jī)器學(xué)習(xí)技術(shù)入門實(shí)戰(zhàn)與大家分享了分類算法,在本文中將為大家介紹聚類算法和關(guān)聯(lián)分析問(wèn)題。分類算法與聚類到底有何區(qū)別?聚類方法應(yīng)在怎樣的場(chǎng)景下使用?如何使用關(guān)聯(lián)分析算法解決個(gè)性化推薦問(wèn)題?本文就為大家揭曉答...
摘要:只需超過(guò)半數(shù)的節(jié)點(diǎn)達(dá)成一致??偨Y(jié)是分布式一致性問(wèn)題中的重要共識(shí)算法。 在一個(gè)分布式系統(tǒng)中,由于節(jié)點(diǎn)故障、網(wǎng)絡(luò)延遲等各種原因,根據(jù)CAP理論,我們只能保證一致性(Consistency)、可用性(Availability)、分區(qū)容錯(cuò)性(Partition Tolerance)中的兩個(gè)。 對(duì)于一致性要求高的系統(tǒng),比如銀行取款機(jī),就會(huì)選擇犧牲可用性,故障時(shí)拒絕服務(wù)。MongoDB、Redis...
摘要:時(shí)間復(fù)雜度場(chǎng)景一一根長(zhǎng)寸的面包,每天吃掉一寸,那么吃完整個(gè)面包需要幾天答案自然是天可以記作場(chǎng)景二一根寸的面包,每天吃掉剩余的一半,吃的只剩下寸,需要多少天答案以為底,的對(duì)數(shù),簡(jiǎn)寫成,所以為天可以記作場(chǎng)景三每天吃掉一個(gè)雞腿,那么吃掉整個(gè)雞腿需 時(shí)間復(fù)雜度 場(chǎng)景一:一根長(zhǎng)10寸的面包,每3天吃掉一寸,那么吃完整個(gè)面包需要幾天?答案自然是:3×10=30天可以記作:T(n) = 3n 場(chǎng)景二...
閱讀 635·2023-04-26 01:53
閱讀 2760·2021-11-17 17:00
閱讀 2895·2021-09-04 16:40
閱讀 1995·2021-09-02 15:41
閱讀 844·2019-08-26 11:34
閱讀 1234·2019-08-26 10:16
閱讀 1343·2019-08-23 17:51
閱讀 830·2019-08-23 16:50