首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >4使用信号量处理4路同步(在C编程中,UNIX环境中)

4使用信号量处理4路同步(在C编程中,UNIX环境中)
EN

Stack Overflow用户
提问于 2014-10-13 20:24:19
回答 1查看 3.3K关注 0票数 0

我有一个关于在UNIX环境中同步4个进程的问题。非常重要的是,没有一个进程不首先等待其他进程“在同一页上”才运行其主要功能。

具体来说,它们都不应该在没有第一次同步的情况下进入它们的循环。如何在4种情况下同步4个进程,使它们在不等待其他进程的情况下进入第一个while循环?注意到这主要是一个逻辑问题,而不是编码问题。

为了保持环境之间的一致性,我们只需要使用操作semaphore_create(int systemID)、semaphore_open(int semaID)、semaphore_wait(int semaID)和semaphore_signal(int semaID)的伪代码信号量库。

以下是我的尝试和随后的想法:

Process1.c:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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路同步。我想这是一个非常普遍的事情,必须考虑取决于行业(例如。银行业务和银行账户同步)。我知道这不是很难,但我以前从来没有用过信号灯,所以我有点困惑它们是如何工作的。

EN

回答 1

Stack Overflow用户

发布于 2014-10-14 19:42:00

模型信号量库的精确语义不够清楚,无法明确地回答您的问题。但是,如果semaphore_create()semaphore_open()之间的区别是后者要求指定的信号量已经存在,而前者要求它不存在,那么是的,如果在任何其他进程试图打开信号量之前process1没有设法创建所需的信号量,那么整个事情就会崩溃。(如果其他语义成立的话,它可能会以不同的方式倒下。)

这种问题在线程场景中是可以避免的,因为有了线程,就必须有一个初始的单线程段,其中可以初始化同步结构。还有共享内存,不同线程之间可以通过共享内存进行通信。答案@Dark指的取决于这些特征。

多个独立进程的障碍--或者不能通过共享内存进行通信的线程--以及最初没有同步的线程的基本问题是,您无法知道哪个进程需要建立这个屏障。因此,每个国家都需要做好这样做的准备。如果semaphore_create()可以向调用方指示已实现的结果,则它可以在您的模型库中工作。

  • 信号量成功创建
  • 信号量已经存在
  • (或错误)

在这种情况下,所有参与的进程(您必须知道其编号)都可以执行相同的过程,可能如下所示:

代码语言:javascript
复制
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阻止已到达障碍的非控制进程,直到控制过程释放它们。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26348297

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档