【问题标题】:Sync N processes using semaphore - condition race使用信号量同步 N 个进程 - 条件竞争
【发布时间】:2018-11-24 15:40:56
【问题描述】:

我正在尝试仅使用信号量(无互斥体)订购 N 个进程。

P1 -> P2 -> P3 -> ... -> Pn

我正在处理这个问题:

如果您致电:

s = 1;

P1 {
wait(s1)
...
signal(s1)
}

P2 {
wait(s1)
...
signal(s1)
}

如何防止它不会在一个进程中开始循环?就像释放信号量的一个进程不会再次接管它?我需要所有流程才能最终轮到我。

我也很感激有关如何解决此类问题(同步 N 个进程)使用信号量而不使用 N 信号量的任何建议,我读到可能的最小值为 3。

谢谢。

【问题讨论】:

标签: multithreading concurrency process operating-system semaphore


【解决方案1】:

这里有一些选项。因为您总是先调用signal,然后再调用wait,所以协程选项可能是最好的。您没有可并行化的代码,因此无法从普通线程中受益。了解如何避免同步也很有用。

  • 您可以使用多个信号量。每个线程明确地将控制权交给下一个线程。

  • 您可以使用 Whose-turn-is-next 变量。获得锁后,线程将检查是否轮到它,如果不是,它将释放锁。这可能会导致旋转,什么都不做。所以我们将不得不添加另一个锁。检查后,我们将等待另一个锁已完成某个线程。这将在线程完成一些工作后被释放。现在线程不旋转。但是,每次一个线程完成时,其他所有线程都会检查它是否是下一个。

到目前为止,直接回答您的问题的解决方案是反模式。您只是在制作一个多线程程序,运行单线程,通过使用信号量来完全同步线程。

这不是模式或反模式,只是一个注释

  • 在 Unix 上,如果线程占用了处理器,并且还有其他线程准备好运行,那么它最终会被取消调度。

更好的方法。

  • 避免需要同步:
    (见https://www.youtube.com/watch?v=2yXtZ8x7TXw)如果不使用可变变量,那么并发很容易,不需要同步。

  • 考虑管道和过滤器:在这种模式下,线程可以通过管道 (fifo) 进行通信。您可以为此使用最小的锁定循环缓冲区(只需确保只将不可变数据放入缓冲区)。 |在 Unix(例如 Gnu/Linux)中,您可以使用管道和进程。您可以使用 fork 在一个程序中完成所有这些操作。或者您可以将多个程序连接在一起(bash 是一个很好的工具)。

  • 考虑微线程/协同例程/协同线程:
    有时编写具有多个独立线程的程序会很好。但是,如果您的线程不会花费大量时间并发运行(例如,因为您总是调用signal; wait),那么您就不需要线程。线程对代码产生了很大的复杂性。因此使用协同例程(或在您的系统上调用它们),它们允许您编写多个例程以独立调度,但只有在调用yield 时控制权才会移交给另一个协同例程(类似于调用signal; wait,但该机制将更愿意移交给环中的下一个协程。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 1970-01-01
    • 2012-05-01
    • 2021-06-04
    • 2012-01-06
    • 2021-09-27
    • 2011-03-26
    相关资源
    最近更新 更多