Lamport面包店算法是解决多个线程并发访问一个共享的单用户资源的互斥问题的算法。由莱斯利·兰波特发明。git
Lamport把这个并发控制算法很是直观地类比为顾客去面包店采购。github
这个类比中的顾客就至关于线程,而入店购货就是进入临界区独占访问该共享资源。因为计算机实现的特色,存在两个线程得到相同的签到号码的状况,这是由于两个线程几乎同时申请排队的签到号码,读取已经发出去的签到号码状况,这两个线程读到的数据是彻底同样的,而后各自在读到的数据上找到最大值,再加1做为本身的排队签到号码。算法
为此,该算法规定若是两个线程的排队签到号码相等,则线程id号较小的具备优先权。并发
Lamport时间戳原理以下:分布式
当知足如下两个条件时,进程A会被分配该资源:ui
private void processRevcMsg(Message m) throws InterruptedException { // 原理4 若是事件属于接收事件,时间戳 = Max(本地时间戳,消息中的时间戳) + 1 clock.update(m.getTimestamp()); lastSendMap.put(m.getFrom(), m); switch (m.getMsgType()) { case REQUEST_RES: // rule 2 当进程B接收到了进程A的(Tm:A)请求后,会把它放到本身的请求队列,而后发送一个带时间戳的确认消息给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 当进程B接收到进程A释放资源的请求,它会移除队列中任意的(Tm:A)的资源请求 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 当知足如下两个条件时,进程A会被分配该资源:a)有一个(Tm:A)的请求,按照=>关系排在队列第一位;b)A接收到了一个时间戳大于Tm的来自全部其余进程的消息 // condition (ii) of rule 5 // A接收到了一个来自全部其余进程的消息,并且时间戳大于Tm for (Map.Entry<Integer, Message> entry : 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 // 有一个Tm:A的请求,按照=>关系排在队列第一位 for (Map.Entry<Integer, List<Message>> 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 为了释放资源,进程A移除全部(Tm:A)的请求消息,而后发送带时间戳的A释放资源请求消息给其余全部的进程程 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(); } } }); } }