彼得森算法

2023-12-13

在经典的 Peterson 算法中,您在进入关键部分之前检查 2 个标志 flag1 和 flag2 以及转变量。如果我先检查转,然后检查标志,这会起作用吗?


是的,如果你先检查一下,它会起作用turn然后检查flag[0] or flag[1]在条件内while().

原因是只有当两个条件都成立时才会执行忙等待。

作为证明,我编写了一个小型 C 程序,模拟两个进程,并在它们之间进行随机切换。

对于关键部分,我在进程 0 中使用这段代码:

global ^= 0x5555;
global ^= 0x5555;
global++;

这在过程 1 中:

global ^= 0xAAAA;
global ^= 0xAAAA;
global++;

两个进程各执行此部分 1000 次。如果两者的关键部分之间存在竞争条件,global模拟结束时可能与 2000 年有所不同。

Code:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef enum
{
  InstrNop,
  InstrHalt,
  InstrSetVarNum,
  InstrJumpVarZero,
  InstrJumpVarNonzero,
  InstrJump,
  InstrIncVar,
  InstrDecVar,
  InstrXorVarNum,
} tInstr;

int ExecuteInstruction(unsigned* Vars, const unsigned* Program, unsigned* Position)
{
  switch (Program[*Position])
  {
  default:
  case InstrHalt:
    return 0;

  case InstrNop:
    (*Position)++;
    break;

  case InstrSetVarNum:
    Vars[Program[*Position + 1]] = Program[*Position + 2];
    (*Position) += 3;
    break;

  case InstrXorVarNum:
    Vars[Program[*Position + 1]] ^= Program[*Position + 2];
    (*Position) += 3;
    break;

  case InstrJumpVarZero:
    if (Vars[Program[*Position + 1]] == 0)
      (*Position) = Program[*Position + 2];
    else
      (*Position) += 3;
    break;

  case InstrJumpVarNonzero:
    if (Vars[Program[*Position + 1]] != 0)
      (*Position) = Program[*Position + 2];
    else
      (*Position) += 3;
    break;

  case InstrJump:
    (*Position) = Program[*Position + 1];
    break;

  case InstrIncVar:
    Vars[Program[*Position + 1]]++;
    (*Position) += 2;
    break;

  case InstrDecVar:
    Vars[Program[*Position + 1]]--;
    (*Position) += 2;
    break;
  }

  return 1;
}

typedef enum
{
  VarGlobal,

  VarCnt0,
  VarCnt1,

  VarFlag0,
  VarFlag1,
  VarTurn,

  VarIdxMax
} tVarIdx;

unsigned Vars[VarIdxMax];

#define USE_PETERSON 01
#define SWAP_CHECKS 01

const unsigned Program0[] =
{
  // cnt0 = 1000;
  InstrSetVarNum, VarCnt0, 1000,

// 3:
#if USE_PETERSON
  // flag[0] = 1;
  InstrSetVarNum, VarFlag0, 1,
  // turn = 1;
  InstrSetVarNum, VarTurn, 1,
// 9:
  // while (flag[1] == 1 && turn == 1) {}
#if SWAP_CHECKS
  InstrJumpVarZero, VarTurn, 17,
  InstrJumpVarZero, VarFlag1, 17,
#else
  InstrJumpVarZero, VarFlag1, 17,
  InstrJumpVarZero, VarTurn, 17,
#endif
  InstrJump, 9,
// 17:
#endif

// Critical section starts
  // global ^= 0x5555;
  // global ^= 0x5555;
  // global++;
  InstrXorVarNum, VarGlobal, 0x5555,
  InstrXorVarNum, VarGlobal, 0x5555,
  InstrIncVar, VarGlobal,
// Critical section ends

#if USE_PETERSON
  // flag[0] = 0;
  InstrSetVarNum, VarFlag0, 0,
#endif

  // cnt0--;
  InstrDecVar, VarCnt0,
  // if (cnt0 != 0) goto 3;
  InstrJumpVarNonzero, VarCnt0, 3,

  // end
  InstrHalt
};

const unsigned Program1[] =
{
  // cnt1 = 1000;
  InstrSetVarNum, VarCnt1, 1000,

// 3:
#if USE_PETERSON
  // flag[1] = 1;
  InstrSetVarNum, VarFlag1, 1,
  // turn = 0;
  InstrSetVarNum, VarTurn, 0,
// 9:
  // while (flag[0] == 1 && turn == 0) {}
#if SWAP_CHECKS
  InstrJumpVarNonzero, VarTurn, 17,
  InstrJumpVarZero, VarFlag0, 17,
#else
  InstrJumpVarZero, VarFlag0, 17,
  InstrJumpVarNonzero, VarTurn, 17,
#endif
  InstrJump, 9,
// 17:
#endif

// Critical section starts
  // global ^= 0xAAAA;
  // global ^= 0xAAAA;
  // global++;
  InstrXorVarNum, VarGlobal, 0xAAAA,
  InstrXorVarNum, VarGlobal, 0xAAAA,
  InstrIncVar, VarGlobal,
// Critical section ends

#if USE_PETERSON
  // flag[1] = 0;
  InstrSetVarNum, VarFlag1, 0,
#endif

  // cnt1--;
  InstrDecVar, VarCnt1,
  // if (cnt1 != 0) goto 3;
  InstrJumpVarNonzero, VarCnt1, 3,

  // end
  InstrHalt
};

void Simulate(void)
{
  unsigned pos0 = 0, pos1 = 0;

  while (Program0[pos0] != InstrHalt ||
         Program1[pos1] != InstrHalt)
  {
    int cnt;

    cnt = rand() % 50;
    while (cnt--)
      if (!ExecuteInstruction(Vars, Program0, &pos0))
        break;

    cnt = rand() % 50;
    while (cnt--)
      if (!ExecuteInstruction(Vars, Program1, &pos1))
        break;
  }
}

int main(void)
{
  srand(time(NULL));
  Simulate();
  printf("VarGlobal = %u\n", Vars[VarGlobal]);
  return 0;
}

Output (ideone):

VarGlobal = 2000

现在,检查顺序与以下相同的程序维基百科,我定义为SWAP_CHECKS为 0:输出(ideone):

VarGlobal = 2000

最后,为了表明当彼得森算法被禁用时存在竞争条件,我定义USE_PETERSON为 0:输出(ideone):

VarGlobal = 1610
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

彼得森算法 的相关文章

  • 如何并行安装/编译 pip 要求(使 -j 等效)

    我的 pip 要求中有很多软件包需要安装 我想并行处理它们 我知道 例如 如果我想要n并行作业来自make我必须写make j n 是否有满足 pip 要求的等效命令 Thanks 有时 pip 使用 make 来构建依赖项 如果在开始之前
  • 大小为 n 的数组,其中一个元素 n/2 次

    给定一个由 n 个整数组成的数组 其中一个元素出现超过 n 2 次 我们需要在线性时间和恒定的额外空间中找到该元素 YAAQ 又一个数组问题 我有一种偷偷的怀疑 这类似于 在 C 中 We don t need an array publi
  • 让电脑实现360度=0度,旋转炮塔

    我正在制作一个游戏 其中有一个计算机控制的炮塔 炮塔可360度旋转 它使用 trig 找出枪瞄准所需的角度 obj deg 并将枪的当前角度存储在 gun deg 下面的代码以设定的速度旋转枪 if objdeg gt gundeg gun
  • PyTorch DataLoader 对并行运行的批次使用相同的随机种子

    有一个bug https tanelp github io posts a bug that plagues thousands of open source ml projects 在 PyTorch Numpy 中 当并行加载批次时Da
  • 操作系统中的用户模式和内核模式有什么区别?

    用户模式和内核模式之间有什么区别 为什么以及如何激活它们 以及它们的用例是什么 内核模式 在内核模式下 执行代码具有完整且不受限制的 访问底层硬件 它 可以执行任何CPU指令并且 引用任意内存地址 核心 模式通常保留给 最低级别 最受信任的
  • 找到一个恰好出现了 N/2 次的数字

    这是我的面试问题之一 给定一个包含 N 个元素的数组以及元素出现的位置正好 N 2次 其余 N 2 个元素是unique 您如何找到运行时间更好的元素 请记住 元素未排序 您可以假设 N 是偶数 例如 input array 10 2 3
  • std::__gcd 和 std::gcd 有什么区别?

    Many https www geeksforgeeks org stdgcd c inbuilt function finding gcd websites https codeforces com submissions Madiyar
  • 运行单个 Java 线程的双核 CPU 利用率[重复]

    这个问题在这里已经有答案了 可能的重复 多线程 Java 应用程序能否很好地利用多核机器 https stackoverflow com questions 1649402 would a multithreaded java applic
  • Parallel.ForEach - 优雅取消

    关于等待任务完成和线程同步的主题 我目前有一个迭代 我已将其包含在 Parallel ForEach 中 在下面的示例中 我在评论中提出了一些关于如何最好地处理循环的优雅终止的问题 NET 4 0 private void myFuncti
  • 具有多个参数和返回值的两个并行函数

    我有两个独立的功能 每一个都需要相当长的时间来执行 def function1 arg do some stuff here return result1 def function2 arg1 arg2 arg3 do some stuff
  • 线性问题和非线性问题之间的区别?点积和核技巧的本质

    核技巧将非线性问题映射为线性问题 我的问题是 1 线性问题和非线性问题的主要区别是什么 这两类问题的差异背后的直觉是什么 核技巧如何帮助在非线性问题上使用线性分类器 2 为什么点积在这两种情况下如此重要 Thanks 当人们说到分类问题的线
  • 使用多处理和 PySftp 并行下载

    我正在尝试创建一个代码来使用 pysftp 和多处理库下载相同类型的 N 个文件 我做了一个基本的Python训练 得到了一些代码并将它们组合成一个 但我无法让它工作 如果有人帮助我 我将不胜感激 该错误发生在 vFtp close 命令之
  • 正则表达式等价

    有没有办法找出两个任意正则表达式是否等价 对我来说看起来很复杂的问题 但可能有一些 DFA 简化机制之类的 要测试等价性 您可以计算的表达式并进行比较
  • 具有主区域的 OpenMP for 循环:“主区域可能不会紧密嵌套在工作共享或显式任务区域内”

    我有以下代码 我相信它应该显示一个进度条 近似整个过程的进度 因为循环的每个并行线程应该以大约相同的速率进行 pragma omp parallel for for long int x 0 x
  • 查找数组中的组合

    我在java中有一个像这样的二维数组 transmission communication tv television approach memorycode methodact 我需要获得所有组合 例如 transmission appr
  • 颜色渐变算法

    给定两种 RGB 颜色和一个矩形 我可以创建一个基本的线性渐变 这博客文章 https bsou io posts color gradients with python关于如何创建它给出了很好的解释 但我想在这个算法中添加一个变量 角度
  • 在小于 O(N) 的时间内找出点是否位于 N 个(可能重叠)矩形之一内

    我有一个图像 我想在鼠标移动到某些矩形区域时显示工具提示 矩形区域最多可达 1000 个 但是 仅检查每个矩形中是否有点 时间复杂度为 O N 导致移动鼠标时界面无响应 有没有办法在小于 O N 的时间内完成它 我可以预先对矩形进行排序 我
  • 归并排序究竟进行了多少次比较?

    我读到 在实践中 快速排序比合并排序快得多 其原因是隐藏常量 那么 随机快速排序复杂度的解是2nlnn 1 39nlogn 这意味着快速排序中的常数是1 39 但是合并排序呢 归并排序中的常数是什么 让我们看看能否解决这个问题 在合并排序中
  • 绘图:仅保留最相关的数据

    为了节省带宽并且不用自己生成图片 图表 我计划使用 Google 的图表 API http code google com apis chart http code google com apis chart 它的工作原理是简单地发出一个
  • Networkx 中 Louvain 分区的可视化

    请帮助我更改 Louvain 聚类算法结果的可视化 我从网站上获取了代码https github com taynaud python louvain https github com taynaud python louvain我可以重写

随机推荐

  • 使用 Bootstrap Datepicker 时如何获取选定的日期值?

    使用 jquery 和 Bootstrap Datepicker 如何获取我使用 Bootstrap Datepicker 选择的新日期值 仅供参考 我正在使用 Rails 3 和 Coffescript 我使用以下方法设置日期选择器
  • 具有多对多关系的 MVC4 控制器

    我有两个实体 Arena 和 Regulator 它们之间具有多对多的关系 我已经实现了 EF 代码首先接受的解决方案 见下文 我现在一直致力于实现控制器视图 以便当用户创建调节器时 他可以选择一个或多个竞技场 可能使用复选框或多选列表 并
  • 通过 xpath Selenium java 选择具有动态生成的 id 的 WebElements

    我需要在下拉窗口中选择一个元素 每次我在正在测试的网站中打开下拉窗口时 网站都会随机生成该下拉窗口的 ID 下拉窗口的先前实例可见 使用 Firebug 但不可选择 有一个静态路径 但仅当我使用 ChromeDriver 测试它时才有效 而
  • 用于任意对象的 python 哈希函数的替代方案

    在python2 7中 我成功使用hash 将对象放入持久存储在磁盘上的存储桶中 样机代码如下所示 class PersistentDict object def setitem self key value bucket index ha
  • 基本 Docker 容器报告运行级别未知

    当我像这样运行一个基本的 Docker 容器 从 Google Cloud Shell 中 时 docker pull debian docker run i t debian wheezy bin bash 然后输入runlevel在运行
  • 查找给定矩阵的子矩阵

    我正在尝试编写一种算法来在给定的子矩阵中查找子矩阵 为了解决这个问题我编写了以下代码 public class SubMatTry param args public static void main String args TODO Au
  • 添加到 Google 日历呈现链接不显示用户的当地时间

    我可以使用此谷歌日历链接创建一个活动 但我认为 UTC 时间即将到来 比我想要的活动时间提前了 5 30 小时 例子 这个链接将创建一个活动 但显示时间为中午 12 30 至下午 4 点 该活动预计在上午 6 30 至上午 10 点进行 根
  • 是否可以使用单个 SQL 语句将记录从一个表移动到另一个表?

    我需要一个查询将记录从一个表移动到另一个表而不使用多个语句 不可以 您不能在一条 SQL 语句中移动记录 你必须使用一个INSERT随后是一个DELETE陈述 您应该将这些语句包装成交易 以确保复制操作保持原子性 START TRANSAC
  • 使用 oauth2 和 Google API 时无法识别的参数

    我在一些脚本中使用 Google API 服务 但遇到了一些问题 这个错误有点奇怪 但我们开始了 我有一个列出我的 Google 云端硬盘文件的脚本 from apiclient import discovery from httplib2
  • 如何获取成员变量的注解?

    我想知道一个类的一些成员变量的注释 我使用BeanInfo beanInfo Introspector getBeanInfo User class 反思一个类 并使用BeanInfo getPropertyDescriptors 查找特定
  • 如何从一个元组到一个元组引用元组中的元素?

    我有一个 C 11 元组 我想要一个元组std reference wrappers 到元组的相同元素 有没有简单的方法可以做到这一点 映射一个元组很容易一组索引 e g include
  • 在代码中处理语音命令以执行命令的智能方法

    我想知道是否可以寻求更好的方法来处理和处理命令 而不是使用可能变得非常长且非常乏味的 Switch Case 或 IF 布尔检查 E G if settings getName Command Speak I am here if Get
  • 如何用 Python 可视化回归树

    我正在寻找可视化回归使用 scikit learn 中的任何集成方法构建的树 梯度增强回归器 随机森林回归器 装袋回归器 我看过这个问题很接近 并且这个问题它处理分类树 但这些问题需要 树 方法 而该方法不适用于 SKLearn 中的回归模
  • 在 Spring Integration 中,RequestHandlerRetryAdvice 无法与 Ftp.outboundGateway 一起使用

    我的情况与描述的类似这个问题 区别在于我不使用WebFlux outboundGateway but an Ftp outboundGateway我称之为AbstractRemoteFileOutboundGateway Command G
  • phpmyadmin 中的自动增量

    我有一个使用 PHP MySQL 和 phpMyAdmin 的现有数据库 当用户成为我网站的会员时 我需要系统使用五位数字为他们创建一个唯一的会员号码 例如 83773 我想这就像生成一个随机密码 只不过我只想要我的会员的数字 该 ID 号
  • urllib2 HTTPPasswordMgr 不起作用 - 凭据未发送错误

    以下 python curl 调用具有以下成功结果 gt gt gt import subprocess gt gt gt args curl H X Requested With Demo https username email pro
  • Jenkinsfile主动选择参数

    如何在多分支管道 Jenkinsfile 声明性 中使用此 dsl 脚本 parameters activeChoiceParam States description Select a state option filterable ch
  • Ajax 如何与 PHP 配合使用?

    我在使用 ajax 和 php 时遇到问题 我想做的是调用一个 ajax 函数 该函数从表单的输入中获取一个值 并检查该电子邮件是否存在于数据库中 这是我当前的 JavaScript Checks for Existing Email fu
  • 如何同步调用ajax而不冻结网页

    我有一些 javascript 可以触发大约 100 个对 php 脚本的调用 php 脚本占用大量内存并需要几秒钟才能完成 然后返回通过或失败的 json 响应 我不希望 ajax 调用是异步的 因为服务器会在运行 100 个自身实例时突
  • 彼得森算法

    在经典的 Peterson 算法中 您在进入关键部分之前检查 2 个标志 flag1 和 flag2 以及转变量 如果我先检查转 然后检查标志 这会起作用吗 是的 如果你先检查一下 它会起作用turn然后检查flag 0 or flag 1