我有一个关于在UNIX环境中同步4个进程的问题。非常重要的是,没有一个进程不首先等待其他进程“在同一页上”才运行其主要功能。
具体来说,它们都不应该在没有第一次同步的情况下进入它们的循环。如何在4种情况下同步4个进程,使它们在不等待其他进程的情况下进入第一个while循环?注意到这主要是一个逻辑问题,而不是编码问题。
为了保持环境之间的一致性,我们只需要使用操作semaphore_create(int systemID)、semaphore_open(int semaID)、semaphore_wait(int semaID)和semaphore_signal(int semaID)的伪代码信号量库。
以下是我的尝试和随后的想法:
Process1.c:
int main() {
//Synchronization area (relevant stuff):
int sem1 = semaphore_create(123456); //123456 is an arbitrary ID for the semaphore.
int sem2 = semaphore_create(78901); //78901 is an arbitrary ID for the semaphore.
semaphore_signal(sem1);
semaphore_wait(sem2);
while(true) {
//...do main functionality of process, etc (not really relevant)...
}
}进程2.c:
int main() {
//Synchronization area (relevant stuff):
int sem1 = semaphore_open(123456);
int sem2 = semaphore_open(78901);
semaphore_signal(sem1);
semaphore_wait(sem2);
while(true) {
//...do main functionality of process etc...
}
}进程3.c:
int main() {
//Synchronization area (relevant stuff):
int sem1 = semaphore_open(123456);
int sem2 = semaphore_open(78901);
semaphore_signal(sem1);
semaphore_wait(sem2);
while(true) {
//...do main functionality of process etc...
}
}程序4.c:
int main() {
//Synchronization area (relevant stuff):
int sem1 = semaphore_open(123456);
int sem2 = semaphore_open(78901);
semaphore_signal(sem2);
semaphore_signal(sem2);
semaphore_signal(sem2);
semaphore_wait(sem1);
semaphore_wait(sem1);
semaphore_wait(sem1);
while(true) {
//...do main functionality of process etc...
}
}我们首先运行Process1,并将所有信号量创建到其他进程中使用的系统内存中(其他进程只需调用semaphore_open以获得对这些信号量的访问)。然后,所有四个进程都有一个信号操作,然后是等待。信号操作导致process1、process2和process3将sem1的值增加1,因此其结果最大值为3(取决于操作系统决定在何种顺序下运行这些进程)。2和3岁的Process1都在等待sem2,process4也在等待sem1。然后,Process 4向sem2发出3次信号,使其值返回到0,并3次等待sem1。由于sem1是来自其他进程中的信令的最大3(同样取决于它们运行的顺序),所以它将使其值返回到0,并继续运行。因此,所有进程都将是同步的。
所以是的,对我的回答不太有信心。我觉得这在很大程度上取决于进程运行的顺序,这就是同步的全部要点--不管它们运行的顺序是什么,它们都正确地同步。而且,我在Process4中做了很多工作。也许用两个以上的信号灯来解决这个问题会更好?如果我想做进一步的同步,这难道不允许在每个进程的循环中有更多的灵活性吗?
我的问题:请解释为什么上述逻辑将工作或将不工作,和/或一个解决方案如何解决这个问题的4路同步。我想这是一个非常普遍的事情,必须考虑取决于行业(例如。银行业务和银行账户同步)。我知道这不是很难,但我以前从来没有用过信号灯,所以我有点困惑它们是如何工作的。
发布于 2014-10-14 19:42:00
模型信号量库的精确语义不够清楚,无法明确地回答您的问题。但是,如果semaphore_create()和semaphore_open()之间的区别是后者要求指定的信号量已经存在,而前者要求它不存在,那么是的,如果在任何其他进程试图打开信号量之前process1没有设法创建所需的信号量,那么整个事情就会崩溃。(如果其他语义成立的话,它可能会以不同的方式倒下。)
这种问题在线程场景中是可以避免的,因为有了线程,就必须有一个初始的单线程段,其中可以初始化同步结构。还有共享内存,不同线程之间可以通过共享内存进行通信。答案@Dark指的取决于这些特征。
多个独立进程的障碍--或者不能通过共享内存进行通信的线程--以及最初没有同步的线程的基本问题是,您无法知道哪个进程需要建立这个屏障。因此,每个国家都需要做好这样做的准备。如果semaphore_create()可以向调用方指示已实现的结果,则它可以在您的模型库中工作。
在这种情况下,所有参与的进程(您必须知道其编号)都可以执行相同的过程,可能如下所示:
void process_barrier(int process_count) {
sem_t *sem1, *sem2, *sem3;
int result = semaphore_create(123456, &sem1);
int counter;
switch (result) {
case SEM_SUCCESS:
/* I am the controlling process */
/* Finish setting up the barrier */
semaphore_create(78901, &sem2);
semaphore_create(23432, &sem3);
/* let (n - 1) other processes enter the barrier... */
for (counter = 1; counter < process_count; counter += 1) {
semaphore_signal(sem1);
}
/* ... and wait for those (n - 1) processes to do so */
for (counter = 1; counter < process_count; counter += 1) {
semaphore_wait(sem2);
}
/* let all the (n - 1) waiting processes loose */
for (counter = 1; counter < process_count; counter += 1) {
semaphore_signal(sem3);
}
/* and I get to continue, too */
break;
case SEM_EXISTS_ERROR:
/* I am NOT the controlling process */
semaphore_open(123456, &sem1);
/* wait, if necessary, for the barrier to be initialized */
semaphore_wait(sem1);
semaphore_open(78901, &sem2);
semaphore_open(23432, &sem3);
/* signal the controlling process that I have reached the barrier */
semaphore_signal(sem2);
/* wait for the controlling process to allow me to continue */
semaphore_wait(sem3);
break;
}
}显然,我在您的库界面上做了一些小的改动,并且我省略了错误检查,除非它们直接影响到屏障的操作。
该示例中涉及的三个信号量具有不同的、定义明确的目的。sem1保护同步结构的初始化,并允许进程选择其中哪些负责控制屏障。sem2负责计算有多少进程达到了障碍。sem3阻止已到达障碍的非控制进程,直到控制过程释放它们。
https://stackoverflow.com/questions/26348297
复制相似问题