论文-分布式-并发控制-Lamport逻辑时钟

news2024/10/7 18:20:49

目录

前言

逻辑时钟讲解

算法类比为面包店内取号

Lamport算法的时间戳原理

Lamport算法的5个原则

举例说明

算法实现

参考文献


  • 前言

  • 在并发系统中,同步与互斥是实现资源共享的关键
  • Lamport面包店算法作为一种经典的解决并发问题的算法,它的实现原理和应用是每个探索并发控制的人必须要了解的知识点
  • Dijkstra于1965年提出的基于共享存储的临界区互斥访问问题
  • Dijkstra提出了基于对内存单元的原子性读写实现的方案
  • 然而,Lamport指出Dijkstra的方案会因为节点在临界区内失效而导致系统死锁
  • 在其于1974年发表的文章A New Solution of Dijkstra’s Concurrent Programming Problem中,Lamport提出了完全基于软件实现的解决方案,被称为“面包店算法”
  • Lamport面包店算法是一种经典的分布式系统中互斥访问共享资源的算法,用来解决多个线程并发访问一个共享的单用户资源的互斥问题,因其设计思想类似于面包店中取号排队的方式,因此被称为面包店算法
  • "面包店算法"模拟面包店内取号服务的模式,实现了先来先服务的的互斥访问
  • 这个算法也可以称为时间戳策略,或者叫做Lamport逻辑时钟
  • 逻辑时钟讲解

  • 这里先陈述一下这个逻辑时钟的内容:
  • 是一种在分布式系统中对事件进行时间戳排序的方法,在其中定义了因果关系,称为before
  • 例如,before在航班满员,航班可预订
  • 这里“事件预订”before“航班满员”,预订和满员就形成了因果关系
  • 现实世界中,确定事件预订发生在事件满员之前,需要预订发生在比满员更早的时间
  • 因果关系是一个事件(因)和第二个事件(果)之间的作用关系,其中后一个事件被认为是前一个事件的结果
  • 一般来说,一个事件是很多原因综合产生的结果,而且原因都发生在较早的时间点
  • 而在分布式系统中,有时不可能说两个事件中的一个首先发生;关系“happened before”只是系统中事件的部分排序
  • 我们用分布式系统中的事件的先后关系,用“->”符号来表示,例如:若事件a发生在事件b之前,那么a->b
  • 该关系需要满足下列三个条件:
    • 1-如果a和b是同一进程中的事件,a在b之前发生,则a->b
    • 2-如果事件a是消息发送方,b是接收方,则a->b
    • 3-对于事件a、b、c,如果有a->b,b->c,则有a->c
  • 注意,对于任何一个事件a,a->a都是不成立的,也就是说,关系->是反自反的
  • 有了上面的定义,我们也可以定义出“并发”(concurrent)的概念了:
    • 对于事件a、b,如果a->b,b->a两个都不成立,那么a和b就是并发的
  • 直观上,上面的->关系非常好理解,即“xxx在xxx之前发生”
  • 也就是说,一个系统在输入I1下,如果有a->b,那么对于这个系统的同一个输入I1,无论重复运行多少次,a也始终发生在b之前;
  • 如果在输入I1下a和b是并发的,则表示在同一个输入I1下的不同运行中,a可能在b之前,也可能在b之后,也可能恰好同时发生
  • 也就是说,并发并不是指一定同时发生,而是表示一种不确定性
  • ->和并发的概念,就是我们理解一个系统时最基础的概念之一了
  • 有了上面的概念,我们可以给系统引入时钟了
  • 这里的时钟就是lamport逻辑时钟
  • 一个时钟,本质上是一个事件到实数(假设时间是连续的)的函数
  • 这个函数将每个事件映射到一个数字,代表这个事件发生的时间
  • 形式一点来说,对于每个进程Pi,都有一个时钟Ci,这个时钟将该进程中的事件a映射到Ci(a)
  • 对于一个事件b,假设b属于进程Pj,那么C(b)=Cj(b)
  • 这里插一句,从这个定义也可以看到大师对分布式系统的理解
  • 分布式系统中不存在一个“全局”的实体
  • 在该系统中,每个进程都是一个相对独立的实体,它们有自己的本地信息(本地Knowledge)
  • 而整个系统的信息则是各个进程的信息的一个聚合
  • 有了时钟的一个“本质定义”还不够,我们需要考虑,什么样的时钟是一个有意义的,或者说正确的时钟
  • 其实,有了前文的->关系的定义,正确的时钟应满足的条件已经十分明显了:
  • 时钟条件:对于任意两个事件a,b,如果a->b,那么C(a)<C(b)
  • 注意,反过来讲这个条件可不成立
  • 如果我们要求反过来也成立,即“如果a->b为假,那么C(a)<C(b)也为假”,那就等于要求并发事件必须同时发生,这显然是不合理的
  • 结合前文->关系的定义,我们可以把上面的条件细化成如下两条:
    • 1-如果a和b是进程Pi中的两个事件,并且在Pi中,a在b之前发生,那么Ci(a)<Ci(b)
    • 2-如果a是Pi发送消息m,b是Pj接收消息m,那么Ci(a)<Cj(b)
  • 上面就定义了合理的逻辑时钟
  • 显然,一个系统可以有无数个合理的逻辑时钟
  • 实现逻辑时钟也相对简单,只要遵守两条实现规则就可以了:
    • 1-每个进程Pi在自己的任何两个连续的事件之间增加Ci值
    • 2-如果事件a是Pi发送消息m,那么在m中应该带上时间戳Tm=Ci(a);如果b是进程Pj接收到消息m,那么,进程Pj应该设置Cj为大于max(Tm,Cj(b))
  • 有了上面逻辑时钟的定义,我们现在可以为一个系统中所有的事件排一个全序,就是使用事件发生时的逻辑时钟读数进行排序,读数小的在先
  • 当然,此时可能会存在两个事件同时发生的情况
  • 如果要去除这种情况,方法也非常简单:如果a在进程Pi中,b在进程Pj中,Ci(a)=Cj(b)且i < j,那么a在b之前
  • 形式化一点,我们可以把系统事件E上的全序关系“=>”定义为:
  • 假设a是Pi中的事件,b是Pj中的事件,那么:a=>b当且仅当以下两个条件之一成立:
    • 1-Ci(a)<Cj(b)
    • 2-Ci(a)=Cj(b) 且 i < j
  • 算法类比为面包店内取号

  • Lamport把上面这些数理逻辑时钟的概念以非常直观地类比为顾客去面包店采购
  • 面包店只能接待一位顾客的采购
  • step1:已知有n位顾客要进入面包店采购,安排他们按照次序在前台登记一个签到号码;该签到号码逐次加1
  • step2:根据签到号码的由小到大的顺序依次入店购货
  • step3:完成购买的顾客在前台把其签到号码归0;如果完成购买的顾客要再次进店购买,就必须重新排队
  • 这个类比中的顾客就相当于线程,而入店购货就是进入临界区独占访问该共享资源
  • 由于计算机实现的特点,存在两个线程获得相同的签到号码的情况,这是因为两个线程几乎同时申请排队的签到号码,读取已经发出去的签到号码情况,这两个线程读到的数据是完全一样的,然后各自在读到的数据上找到最大值,再加1作为自己的排队签到号码
  • 为此,该算法规定如果两个线程的排队签到号码相等,则线程id号较小的具有优先权
  • 进入临界区
    • 已经拿到排队签到号码的线程,要轮询检查自己是否可以进入临界区
    • 即检查n个线程中,自己是否具有最小的非0排队签到号码;或者自己是具有最小的非0排队签到号码的线程中,id号最小的
    • 可以用伪代码表示上述检查:

  • 非临界区
    • 一旦线程在临界区执行完毕,需要把自己的排队签到号码置为0,表示处于非临界区
  • 把该算法原理与分布式系统相结合,即可实现分布式锁
  • 注意这个系统中需要引入时钟同步,博主的意见是可以采用SNTP实现时钟同步(非权威,仅供参考)
  • Lamport算法的时间戳原理

  • 由部分排序可知,问题的关键点在于节点间的交互要在事件发生顺序上达成一致,而不是对于时间达成一致
  • 所以,逻辑时钟指的是分布式系统中用于区分时间发生顺序的机制
  • 从某种意义上来讲,现实世界的物理时间其实是逻辑时钟的特例
  • 分布式系统中,按是否存在节点交互可分为三类事件,节点内部,发送事件,接收事件
  • 每个事件对应一个Lamport时间戳,初始值为0
  • 如果事件在节点内发生,时间戳+1
  • 如果事件属于发送事件,时间戳+1并在消息中带上该时间戳
  • 如果事件属于接收事件,时间戳=Max(本地时间戳,消息中的时间戳)+1
  • Lamport算法的5个原则

  • 通过五条规则定义算法,为了方便起见,假设每个规则定义的操作形成单个事件:
    • 为了请求资源,进程A发送消息(Tm:A)给所有的其他进程,并且把这个消息放到进程队列中,Tm是消息的时间戳
    • 当进程B接收到了进程A的(Tm:A)请求后,会把它放到自己的请求队列,然后发送一个带有时间戳的确认消息给A
    • 为了释放资源,进程A移除所有(Tm:A)的请求消息,然后发送带时间戳的A释放资源请求消息给其他所有的进程
    • 当进程B接收到进程A释放资源的请求,它会移除队列中任意的(Tm:A)的请求资源
    • 当满足以下两个条件时,进程A会被赋予资源:
      • 1-有一个(Tm:A)的请求,按照=>关系排在队列第一位(它在队列中=>其他请求(为了定义=>,我们定义一个消息,使用发送消息的事件来识别))
      • 2-A接收到了一个时间戳大于Tm的来自所有其他进程的消息
  • 举例说明

  • 在下面这幅图中,我们可以看到现在有三个进程请求临界资源,分别是P1,P2,P3
  • 在P2时间戳=33时,时间戳+1,P2将34写入自己的队列,P2发送request信号分别给三个进程

  • 在P3时间戳=38时,P3收到P2的request信号,将34写入自己的队列,P3时间戳+1,向P2发送时间戳为39的reply信号

  • 在P1时间戳=40时,P1时间戳+1,P1将41写入自己的队列,P1发送request信号分别给三个进程;此时P1还没有收到P2的请求信号

  • 在P1时间戳=42时,P1收到P2的request信号,将34写入自己的队列,P1时间戳+1,向P2发送时间戳为43的reply信号

  • 在P2收到其中一个进程的reply信号后,因为队头是自己的时间戳,所以P2进入临界区开始使用资源

  • 在P3时间戳=42时,P3收到P1的request信号,将41写入自己的队列,P3时间戳+1,向P1发送时间戳为43的reply信号

  • 在P2时间戳=42时,P2收到P1的request信号,将41写入自己的队列,P2时间戳+1,向P1发送时间戳为43的reply信号

  • 在P2时间戳=48时,向其他两个进程发送release信号,并将其在本地队列中释放,也在其他队列中释放

  • 现在我们可以通过这个时空图回顾一下上述过程

  • 注意到在本地时间44,P2或许开始使用资源,因为它已经收到来自P1值为41的时间戳的消息,比P2值为34的时间戳的需求消息更大
  • 此算法按照“发生在先”关系的顺序授予资源(无优先级倒置)
  • 算法实现

  • 定义
    • 数组Choosing[i]为真,表示进程i正在获取它的排队登记号
    • 数组Number[i]的值,是进程i的当前排队登记号;如果值为0,表示进程i未参加排队,不想获得该资源;规定这个数组元素的取值没有上界
    • 正在访问临界区的进程如果失败,规定它进入非临界区,Number[i]的值置0,即不影响其它进程访问这个互斥资源
  • 代码

  • 细节讨论
    • 每个线程只写它自己的Choosing[i]、Number[i],只读取其它线程的这两个数据项
    • 这个算法不需要基于硬件的原子(atomic)操作实现,即它可以纯软件实现
    • 使用Choosing数组是必须的
    • 假设不使用Choosing数组,那么就可能会出现这种情况:
      • 设进程i的优先级高于进程j(即i<j),两个进程获得了相同的排队登记号(Number数组的元素值相等)
      • 进程i在写Number[i]之前,被优先级低的进程j抢先获得了CPU时间片,这时进程j读取到的Number[i]为0,因此进程j进入了临界区
      • 随后进程i又获得CPU时间片,它读取到的Number[i]与Number[j]相等,且i<j,因此进程i也进入了临界区
      • 这样,两个进程同时在临界区内访问,可能会导致数据腐烂(data corruption)
      • 算法使用了Choosing数组变量,使得修改Number数组的元素值变得“原子化”,解决了上述问题
    • 具体实现时,可以把上述伪代码中的忙等待(busy wait),换成交出线程的执行权,例如yield操作
  • 参考文献

  • Original Paper
  • On his publications page,Lamport has added some remarks regarding the algorithm

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1121266.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VTM/VVC 编译与测试-- YUV与RGB空间转换

环境配置:ubuntu 18.04 一、VVC测试 软件下载: 官网下载 VVC:http://jvet.hhi.fraunhofer.de/ 这里可以选择版本。 编译工具: 在开始编译前,需要电脑的环境中中有gcc、g++、cmake、make这四个工具。 sudo apt-get install gcc g++ sudo apt-get install cmake sudo …

Android微信逆向--实现发朋友圈动态

Android微信逆向--实现发朋友圈动态 0x0 前言# 最近一直在研究Windows逆向的东西&#xff0c;想着快要把Android给遗忘了。所以就想利用工作之余来研究Android相关的技术&#xff0c;来保持对Android热情。调用微信代码来发送朋友圈动态一直是自己想实现的东西&#xff0c;研…

Internet Download Manager 逆向分析

写在前面 文章仅供学习&#xff0c;切勿用于商业用途&#xff0c;出于版权原因&#xff0c;文章不提供资源下载。 论坛上较早之前已经有前辈对IDM的序列号算法进行过逆向分析 以及最近有师傅尝试对本篇文章对象相同的版本进行了逆向分析&#xff0c;但是比较遗憾的是该文章并…

瑞萨e2studio(26)----SPI驱动TFT-LCD屏

瑞萨e2studio.26--SPI驱动TFT-LCD屏 概述视频教学csdn课程样品申请完整代码下载屏幕接口接线方式新建工程工程模板保存工程路径芯片配置工程模板选择时钟配置开始SPI配置SPI属性配置IO配置头文件定义回调函数lcd_init.clcd.c设置区域颜色显示字符串显示汉字显示图片结果演示 概…

点击查看详情 | 网页版微信客户管理系统如何操作试用?

微信作为我们日常生活中最常用的社交应用之一&#xff0c;早已成为我们与朋友、家人和同事保持联系的重要工具&#xff0c;也是营销引流的重要平台。 通过微信营销&#xff0c;可以比较精准定向亲近用户。而微信的功能并没有很能满足做微信营销的人群&#xff0c;所以我们需要借…

S5PV210裸机(五):定时器

本文主要探讨210定时器相关知识&#xff0c;210定时器主要包含PWN定时器&#xff0c;系统定时器&#xff0c;看门狗&#xff0c;RTC。 PWM定时器 210有5个PWM定时器,timer0、1、2、3通过对应PIO产生PWM波形信号并输出,timer4没有GPIO只产生内部定时器中断 PWM…

Python 安装CSF(布料模拟滤波)的环境配置

一、环境配置 1.1 下载源码: Github下载CSF库源码 1.2 解压文件如下: 二、安装CSF库 2.1在解压文件中找到python文件夹所在目录 2.2 输入cmd并回车,来打开终端窗口 2.3激活虚拟环境 通过: activate +你的虚拟环境名称。来激活安装CSF库的虚拟环境。【不执行此

k8s镜像加devops

展示 1.配套资料2.devops 3.elk日志收集 4.grafana监控 5.dashboard![在这里插入图片描述](https://img-blog.csdnimg.cn/bf294f9fd98e4c038858a6bf5c34dbdc.png 目的 学习k8s来来回回折腾很久了&#xff0c;光搭个环境就能折腾几天。这次工作需要终于静下心来好好学习了一…

【USMA】N1CTF2022-praymoon

前言 本题主要利用 USMA 解题&#xff0c;当然还有其他做法&#xff0c;暂时不表 程序分析 启动脚本就不看了&#xff0c;该开的保护都开了。看下文件系统初始化脚本&#xff1a; #!/bin/shmkdir /tmp mount -t proc none /proc mount -t sysfs none /sys mount -t devtmpf…

codeforces (C++ Haunted House)

题目&#xff1a; 翻译&#xff1a; 思路&#xff1a; 1、由题目可知&#xff0c;他想让我们判断交换相邻字符位置后将二进制转为十进制后&#xff0c;能否整除2的次方。能整除即输出需要交换的次数&#xff0c;不能则输出-1。&#xff08;例&#xff1a;输入3和010这组数据就…

二分查找:如何快速定位IP对应的省份地址?

文章来源于极客时间前google工程师−王争专栏。 通过IP地址查找IP归属地功能&#xff1a; 这个功能是通过维护一个很大的IP地址库来实现。地址库中包含IP地址范围和归属地的对应关系。 当我们查询202.201.133.13这个IP地址归属地时&#xff0c;在地址库中搜索&#xff0c;这个…

真实感受:是智能家居在选择合适的技术!

科技从来都是为了让我们的生活更加的简单、舒适&#xff0c;而智能家居的智能&#xff0c;体现在如何更更更方便的使用我需要控制的家居。 例如&#xff1a;下班躺在床上想休息&#xff0c;房间和大厅的灯还开着&#xff0c;这时你会选择什么产品躺着解决问题&#xff1f; 红外…

【MySQL】逻辑架构

逻辑架构 逻辑架构剖析服务器处理客户端请求连接层服务层SQL Interface : SQL接口Parser : 解析器Optimizer : 查询优化器Caches&Buffers : 查询缓存组件 引擎层存储层 SQL执行流程MySQL查询流程查询缓存解析器词法分析语法分析 优化器执行器 数据库缓冲池 逻辑架构剖析 服…

云安全—责任共担

0x00 前言 云安全的职责范围实际上一直遵循的是&#xff0c;谁提供谁负责&#xff0c;如果交付给云消费者的时候&#xff0c;交付者使用过程中就要自行负责&#xff0c;也就是我们经常遇到的配置不当等问题&#xff0c;在三层服务模式中&#xff0c;责任互相嵌套&#xff0c;最…

软件测试(五)自动化 selenium

文章目录 自动化测试单元测试&#xff1a;单元测试&#xff1a;UI自动化 selenium工具定义特点&#xff1a;原理&#xff1a;seleniumjava环境搭建SeleniumAPI获取测试结果&#xff1a;添加等待浏览器操作键盘事件鼠标事件多层框架/窗口定位下拉框处理弹窗处理上传文件操作关闭…

10种常用基础模块电路,电子控制不再是难题!

你是否曾经为电子控制中的复杂电路而烦恼&#xff1f; 现在&#xff0c;我将向你展示10个最具实用性和普遍性的模块电路图&#xff0c;让你轻松掌握电子控制的核心技术&#xff01; 这些电路图不仅简单易懂&#xff0c;而且非常具有趣味性&#xff1a; 1、RS232通讯电路&…

Java面试——RPC协议

涉及到分布式方面知识的话&#xff0c;RPC协议是逃不开的&#xff0c;所以在此记录一下RPC协议。 什么是RPC协议 RPC协议&#xff08;Remote Procedure Call&#xff09;远程过程调用&#xff0c;简单的来说&#xff1a;RPC协议是一种通过网络从远程计算机程序获取服务的协议…

【unity小技巧】实现无限滚动视图和类似CSGO的开箱抽奖功能及Content Size Fitter组件的使用介绍

文章目录 一篇一句前言素材一、无限滚动视图1. 绘制视图2. Content Size Fitter是布局控件&#xff08;1&#xff09;在文本框中使用&#xff08;2&#xff09;控制Scroll View(Scroll Rect组件)控件下Content的大小 3. 控制视图无限滚动4. 向右拉无限滚动5. 修复滚动视图一卡一…

julia笔记:字符和字符串

1 字符 Char类型的值代表单个字符 ca #a: ASCII/Unicode U0061 (category Ll: Letter, lowercase)typeof(c) #Char 将 Char 转换为其对应的整数值&#xff0c;即 Unicode 代码 cInt(c) c #97typeof(c) #Int64 将一个整数值&#xff08;Unicaode&#xff09;转回 Char Cha…

杂谈:DC对Verilog和SystemVerilog语言的支持

DC对Verilog和SystemVerilog语言的支持 设计语言用哪种&#xff1f;Design Compiler对二者的支持简单的fsm电路测试测试结果对比写在最后 设计语言用哪种&#xff1f; 直接抛出结论&#xff1a;先有电路&#xff0c;后为描述。设计端而言&#xff0c;没有语言的高低好坏&#…