【问题标题】: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,所以协程选项可能是最好的。您没有可并行化的代码,因此无法从普通线程中受益。了解如何避免同步也很有用。
到目前为止,直接回答您的问题的解决方案是反模式。您只是在制作一个多线程程序,运行单线程,通过使用信号量来完全同步线程。
这不是模式或反模式,只是一个注释
- 在 Unix 上,如果线程占用了处理器,并且还有其他线程准备好运行,那么它最终会被取消调度。
更好的方法。
避免需要同步:
(见https://www.youtube.com/watch?v=2yXtZ8x7TXw)如果不使用可变变量,那么并发很容易,不需要同步。
考虑管道和过滤器:在这种模式下,线程可以通过管道 (fifo) 进行通信。您可以为此使用最小的锁定循环缓冲区(只需确保只将不可变数据放入缓冲区)。 |在 Unix(例如 Gnu/Linux)中,您可以使用管道和进程。您可以使用 fork 在一个程序中完成所有这些操作。或者您可以将多个程序连接在一起(bash 是一个很好的工具)。
考虑微线程/协同例程/协同线程:
有时编写具有多个独立线程的程序会很好。但是,如果您的线程不会花费大量时间并发运行(例如,因为您总是调用signal; wait),那么您就不需要线程。线程对代码产生了很大的复杂性。因此使用协同例程(或在您的系统上调用它们),它们允许您编写多个例程以独立调度,但只有在调用yield 时控制权才会移交给另一个协同例程(类似于调用signal; wait,但该机制将更愿意移交给环中的下一个协程。