【问题标题】:Usage of atomic integer in a shared data在共享数据中使用原子整数
【发布时间】:2016-04-01 06:33:54
【问题描述】:

我正在研究操作系统和同步,我想知道如何在不同步的情况下处理这些共享数据,但我不确定它是否会起作用。这里是代码

现在,竞态条件显然是共享数据中的增量和减量。但是如果整数变量是原子的呢?我想当我只是 CS 的初学者时,我读过一些关于这个的东西,所以问题可能并不完美。据我所知,它阻止了一些东西来防止同时增加和减少。现在,我对此有点困惑,因为如果原子变量真的有效,就不需要为这样的简单代码找到同步方法一个。

注意:代码已被删除,因为它只是改变了人们的焦点并且答案提供了足够的信息

【问题讨论】:

  • 现在你的问题是完整的问题......

标签: c multithreading integer atomic pid


【解决方案1】:

就目前而言,代码并发调用确实不安全,因此必须有某种同步来防止这种情况发生。

现在,关于使num_processes 原子化的想法,这可能会奏效。不过,这不是一个简单的替换,特别是与最大值相比,增量必须以原子方式完成,而不是分两步完成,否则你仍然有竞争条件。特别是,必须防止以下步骤:

  1. 线程 A 检查是否已达到限制,但未达到。
  2. 线程 B 检查是否已达到限制,但未达到。
  3. 线程 B 增加 PID 计数器。
  4. 线程 A 增加 PID 计数器。

每个步骤本身都是原子的,但显然这无助于防止 PID 溢出。相反,代码必须检查计数器是否未达到限制,然后自动递增。这也是一项常见任务(比较和递增),因此您应该很容易找到现有的代码示例。

但是,我很确定这并不是所涉及的所有代码,并且一些其他代码(例如 get_processID() 或释放 PID 的代码)仍可能需要锁定整个代码。

【讨论】:

  • 问题中的代码是一个关于竞争条件和编写锁以防止它的简单问题。我明白了你的意思(我认为。)原子的东西必须是不可分割的,所以比较和增量必须用一个函数来完成。你能详细说明一下吗。顺便说一句,我已经接受你的回答是合法的,因为它证实了我的想法但多一点信息会更好。
  • 我试图说明使用非原子测试和递增如何导致竞争条件。
  • 如果有可用的原子比较交换操作,比较和递增可以在一个简单的步骤中有效地完成。
【解决方案2】:

对于您的代码,根本不需要同步,因为这里 num_processes 仅由一个进程(即父进程)递增和递减。而且 num_processes 在这里不是共享变量。要创建共享变量,您必须首先了解 UNIX 中的 shmget()shmat() 函数。
如果两个或多个进程想要访问共享内存,则会出现竞争条件。如果该操作将完全执行(即没有切换)或根本不执行,则该操作将是原子的。例如
考虑共享数据的增量运算符。该运算符不是原子的。因为如果转到增量运算符的低级指令,则此操作分几个步骤执行:

1. First load the value of variable in some register.
2. Add one with that loaded value and now result will be in some temporary register.
3. Store this result in the memory location / register that is pointed by that variable on which increment is performed.

现在正如您所见,此操作分三步完成。因此,如果在完成这三个步骤之前切换到另一个流程,则会导致不良结果。有关更多信息,您可以从此链接http://tutorials.jenkov.com/java-concurrency/race-conditions-and-critical-sections.html 阅读有关比赛条件的信息。从上面您可以看到add, store, load 指令是原子的,因为考虑到没有电源故障或系统故障,它将完全执行或根本不执行。所以要执行increment operation atomic,我们需要使用semaphoresmonitors 进行一些同步。这些都是软件同步技术。我想现在你会清楚这个话题了..

【讨论】:

  • 我了解原子部分,但我很确定这包括一个竞争条件。因为在 cmets 中它说 fork() 的实现调用了这个函数,这将产生两个进程。我想在不误导问题的情况下提供尽可能少的信息,因为问题更多的是关于原子值而不是分叉。但是您是对的,我现在将其添加到问题中。
  • 恐怕你的假设是错误的,@Shiv。至少我的代码是内核级代码,因此它在所有进程之间共享。此外,由于这是示例代码,而不是现有完整操作系统内核的一部分,因此甚至可能不提供共享内存支持。
  • @UlrichEckhardt 请解释我哪里错了...这样我会更正并理解这一点...
  • 如果它在内核空间中运行(我假设它,我自己不知道),那么它在进程之间共享并且可以同时调用。无论如何,我确信这个问题是基于代码同时调用的假设。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-01
  • 2012-08-16
  • 1970-01-01
  • 2018-05-12
  • 2013-06-13
相关资源
最近更新 更多