我正在尝试仅使用信号量(不使用互斥锁)对N个进程进行排序。
P1-> P2-> P3-> ...-> Pn
我正在处理此问题:
如果您致电:
s = 1;
P1 {
wait(s1)
...
signal(s1)
}
P2 {
wait(s1)
...
signal(s1)
}
如何防止它不会在一个过程中开始循环?就像释放信号量的一个过程不会再接管它一样?我需要所有流程来最终转弯。
我也很感激关于如何解决这种问题(同步N个进程)的任何建议,仅使用信号量,而不使用N个信号量,我读到最小可能为3。
谢谢。
答案 0 :(得分:0)
以下是一些选项。因为您总是总是紧接着先呼叫signal
,然后再呼叫wait
,所以协同例程选项可能是最好的。您没有可并行化的代码,因此无法从普通线程中受益。了解避免同步的需求也将很有用。
您可以使用多个信号灯。每个线程在哪里将控制权明确交给下一个线程。
您可以具有Whose-turn-is-next变量。获取锁后,线程将检查是否轮到它了,否则,将释放该锁。这可能导致旋转,什么也不做。因此,我们将不得不添加另一个锁。检查后,我们将等待另一个锁已经完成了某个线程。线程完成某些工作后,将释放此空间。现在线程不旋转。但是,每当一个线程结束时,其他所有线程都会检查它是否是下一个线程。
到目前为止,直接回答您的问题的解决方案是反模式。您只是通过使用信号量完全同步线程来制作多线程程序,运行单线程。
这是一个模式或反模式,只是一个音符
更好的方法。
避免同步:
(请参阅https://www.youtube.com/watch?v=2yXtZ8x7TXw)如果您不使用可变变量,那么并发就很容易,并且不需要同步。
考虑管道和过滤器:在这种模式下,线程可以通过管道(fifo)进行通信。您可以为此使用最小锁定的循环缓冲区(只需确保仅将不可变数据放入缓冲区中)。 |在Unixes(例如Gnu / Linux)中,可以使用管道和进程。您可以使用fork在一个程序中完成全部操作。或者,您可以将多个程序连接在一起(bash是一个很好的工具)。
考虑微线程/协同例程/协同线程:
有时编写带有多个独立线程的程序会很不错。但是,如果您的线程没有花大量时间并行运行(例如,因为您始终调用signal; wait
),那么就不需要线程。线程给代码带来了极大的复杂性。因此,请使用协同例程(或在系统上调用的例程),它们使您可以编写几个独立调度的例程,但是只有在调用yield
时,控制权才会移交给另一个协同例程(类似于调用signal; wait
,但该机制将更愿意移交给环中的下一个协同例程。