zoukankan      html  css  js  c++  java
  • 进程互斥软件实现之Lamport面包店算法

    一. 进程互斥的实现方式

    1. 软件方式:

    保护临界区, 自己编写代码来实现对进程的控制.

    Dekker算法
    Peterson算法
    Lamport算法等

    2. 硬件方式:

    使用特殊指令保护临界区.

    开关中断指令
    测试并加锁指令
    交换指令
    忙等待, 自旋锁


    二. Lamport面包店算法

    解决多线程并发访问同一个共享资源的互斥问题

    这个思想来自于面包店, 医院等, 需要排队取号的场所. 顾客进入面包店前,首先抓取一个号码,然后按号码从小到大的次序依次进入面包店购买面包.

    前提:
    面包店按由小到大的次序发放号码
    两个或两个以上的顾客有可能得到相同号码
    当多个顾客抓到相同号码,则按顾客名字的字典次序排序

    基本思想:
    发号器按由小到大的次序发放号码. 进程进入临界区前先抓取一个号码, 然后按号码从小到大的次序依次进入临界区. 若多个进程抓到相同的号码则按进程编号依次进入.

    伪算法:

     1 // 变量说明:
     2 // i 表示当前进程PID
     3 // j 表示当前迭代到的进程PID
     4 // choosing[i] 表示当前进程i是否正在取号, 默认值为false
     5 // number[i] 表示当前进程i的排队号, 默认值为0
     6 
     7 process(i) {
     8     while (true) {
     9         // 当前进程i正在取号
    10         choosing[i] = true;
    11         // number为上一个已发放的排队号加1
    12         number[i] = 1 + max(number[1], number[2], ..., number[n-1]);
    13         // 当前进程i取号完毕
    14         choosing[i] = false;
    15         
    16         // 迭代所有进程
    17         for (j = 0; j < n; j++)
    18         {
    19             // 若当前迭代到的进程j正在取号, 则等待其取号完毕
    20             while(choosing[j]);
    21 
    22             // 同时满足, 当前进程才能通过
    23             while (number[j] != 0 && (number[j], j) < (number[i], i));
    24         }
    25 
    26         // 临界区代码
    27 
    28         // 当前进程注销排队号
    29         // 一旦线程在临界区执行完毕,需要把自己的排队签到号码置为0,表示处于非临界区
    30         number[i] = 0;
    31 
    32         // 其它代码
    33 
    34     }     
    35 }

    注意:
    1) 进程需要排队等待的三种情况:
    情况1: 存在没有取得排队号的进程
    情况2: 当前迭代到的进程没有取得排队号
    情况3: 当前迭代到的进程的排队号小于当前进程的排队号, 或当前迭代到的进程PID小于当前进程PID

    2) 只有当前进程注销了排队号, 在排队的其它进程才能进入临界区, 满足进程互斥和有限等待

    3) 符号说明: (a, b) < (c, d) 表示 (a < c) or ((a == c) and (b < d))

    4) 使用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数组的元素值变得"原子化", 解决了上述问题

    后续:

    在Linux上实现编写C程序实现面包店算法

    参考:
    1. 《算法之美》—进程互斥软件算法(Lamport面包店算法和Eisenberg算法)
    https://www.xuebuyuan.com/647028.html
    2. 面包店算法 - CSDN
    https://blog.csdn.net/yucan1001/article/details/7973075

  • 相关阅读:
    前端程序员学好算法系列(七)二叉树和递归
    前端程序员学好算法系列(六)队列
    前端程序员学好算法系列(五)栈
    前端程序员学好算法系列(四)链表
    前端程序员学好算法系列(三)链表
    前端程序员学好算法系列(二)数组
    前端程序员学好算法系列(一)数组
    egg.js-基于koa2的node.js入门
    vuex所有核心概念完整解析State Getters Mutations Actions
    关于vue2用vue-cli搭建环境后域名代理的http-proxy-middleware解决api接口跨域问题
  • 原文地址:https://www.cnblogs.com/shaohsiung/p/9881334.html
Copyright © 2011-2022 走看看