【问题标题】:Synchronization between processes with for loops using semaphores使用信号量在带有 for 循环的进程之间进行同步
【发布时间】:2017-02-06 02:56:16
【问题描述】:

上下文:

  • 我试图让两个进程写入共享内存空间中的同一个数组。

  • 每个进程都会用 for 循环写入数组的一半。

  • 数组的第一个元素将始终存储要写入的下一个元素的索引。

  • IPC 是通过共享内存中的信号量完成的。

前提条件:

  1. 数组和信号量都在共享内存中正确设置。
  2. 如果我在 for 循环之外等待 sem_wait 和 sem_post,程序可以正常工作,这意味着使整个过程原子化。 (这也是我认为信号量和数组设置正确的原因)

问题

但是,当我尝试通过将 sem_wait 和 sem_post 放入 for 循环来减少临界区域时。它不是同步的,因为有一部分数组没有被写入。但是这两个进程完成了它们的循环,总循环数应该等于数组长度。

非常感谢建议为什么会发生这种情况???


更新

在 OS X 上,sem_init() 没有按预期工作。使用 sem_open() 来解决问题。 参考:http://lists.apple.com/archives/darwin-dev//2008/Oct/msg00044.html

【问题讨论】:

  • 我不清楚您遇到了什么问题 - 它不同步 - 信息量不大。此外,您确实应该提供一个最低限度的工作代码示例,在大多数情况下,试图从伪代码中找出问题是不可能的。此外,创建重现问题的工作代码通常是自己实际解决问题的最快方法!
  • @Jackson 感谢您的反馈。事实上,我会说工作代码 sn-ps 与伪代码有 90% 的相似性。如果不包括所有设置,就不可能有一些工作代码。这就是为什么我不只是复制粘贴我的代码。详细阐述了这个问题。
  • 如果没有工作代码示例,我们无法查看您是否正确处理错误、正确创建信号量或执行其他导致问题的操作。你不太可能得到一个明智的答案,你的问题最终会结束。如果您还没有这样做,请阅读有关提问和创建最小工作示例的帮助部分。
  • 伪代码的问题是它只显示了预期的处理,这里似乎是正确的。所以问题应该隐藏在未显示的细节中,比如array volatile,或者信号量是如何初始化的?

标签: c multithreading semaphore


【解决方案1】:

查看您的实际代码,我认为问题在于您如何创建信号量。如果您阅读了 sem_init 的手册页:

如果 pshared 不为零,则信号量在 进程,并且应该位于共享内存区域(请参阅 shm_open(3)、mmap(2) 和 shmget(2))。 (自从一个孩子由 fork(2) 继承其父级的内存映射,它也可以访问 信号量。)任何可以访问共享内存区域的进程都可以 使用 sem_post(3)、sem_wait(3) 等对信号量进行操作。

这里的关键是粗体文本 - 您的信号量不在共享内存中,因此它并没有真正在两个进程之间共享,因此您看到了争用。

【讨论】:

  • 信号量确实是在函数newSemaphore函数内部的共享内存中创建的。我在评论中指出了这一点。此外,如果信号量未正确初始化。以前的贪婪版本应该也不能正常工作。
  • 在这种情况下,调用 sem_wait() 和 sem_post() 会返回什么?如果孩子的调用失败,您没有检测到这一点,程序将继续进行,就好像它没有锁一样。那将是接下来要检查的事情。
  • 我发现了问题。最初使用的 sem_init 在 OS X 上无法正常工作。所以我改为sem_open,问题解决了。感谢您指出错误信息检查!
【解决方案2】:

在问题案例的伪代码中,父线程一释放就需要信号量。现在,由于信号量可用,父级将继续执行。当它的时间片到期时,内核可能会切换到子进程,但它正在等待信号量。信号量由父进程获取。所以再次 parent 将继续执行。

在这种情况下,父级执行了两次,而子级没有执行。

这可能导致执行不同步。

【讨论】:

    猜你喜欢
    • 2023-01-29
    • 2015-04-13
    • 2021-04-25
    • 2016-07-31
    • 2012-01-04
    • 2015-05-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多