【问题标题】:POSIX semaphores: synchronization problemPOSIX 信号量:同步问题
【发布时间】:2011-06-03 17:49:02
【问题描述】:

我在使用 posix 信号量进行同步时遇到问题。这是我写的代码

sem_t *sem1, *sem2;

void* test1() {
    int rv;

    while(1) {
        rv = sem_wait(sem1);
        printf("sem_wait(&sem1) = %d\n",rv);
        printf("test1\n");

        rv = sem_post(sem2);
        printf("sem_post(&sem2) = %d\n\n",rv);
    }
    return NULL;
}

void* test2() {

    while(1) {

        rv = sem_wait(sem2);
        printf("sem_wait(&sem2) = %d\n",rv);
        printf("test2\n");

        rv = sem_post(sem1);
        printf("sem_post(&sem1) = %d\n\n",rv);
    }
    return NULL;
}

int main (int argc, const char * argv[]) {

pthread_t t1,t2;

sem1 = sem_open("sem1", O_CREAT | O_EXCL, 0644, 1);

if (sem1 == SEM_FAILED){
    perror("sem1_init");
    sem_close(sem1);
    return;
}   

sem2 = sem_open("sem2", O_CREAT | O_EXCL, 0644, 0);
if (sem2 == SEM_FAILED){
    perror("sem2_init");
    sem_close(sem1);
    sem_close(sem2);
    return;
}

pthread_create(&t1, NULL, &test1, NULL);
pthread_create(&t2, NULL, &test2, NULL);

pthread_join(t1, NULL);
pthread_join(t2, NULL);

return 0;
}

我的预期是,由于我将sem1 初始化为 1,sem2 初始化为 0,test1 将是第一个运行的函数,然后它们将交替运行直到时间结束。
相反,它不起作用,我的意思是在日志中我读了很多次“test1”,很多次“test2”,有一段时间交替出现,然后又没有任何顺序。 有人可以告诉我我的错误在哪里吗?

ps。不知道它是否有用,但我正在运行 MacOSX 10.6.7


编辑: 我更新了我的代码,删除了对sem_initsem_getvalue 的所有调用(在MacOS 下都不存在),使用sem_open 来初始化信号量,它似乎可以工作。
然而,我发现了一个奇怪的问题,可能是因为我对sem_open 调用的误解:每次我重新启动程序时,如果我为信号量重用相同的名称,我都会收到错误File exists。如何强制重用相同的标识符?

除了。根据手册页,sem_wait 如果成功则返回 0,否则返回 -1。如果我收到 1 意味着什么(这总是发生在 test2 中)?

【问题讨论】:

  • 首先,编译启用警告的程序。此外,检查所有调用的返回值是否存在错误。然后,看看这个 stackoverflow.com/questions/1413785/sem-init-on-os-xstackoverflow.com/questions/4136181/… 是不是你的问题。
  • @nos 哇,如果我可以给苹果一个-1,因为我没有实现这个,我会的。 :P(当然,我同意:总是检查错误......)
  • asveikau 是对的,MacOS 下似乎没有sem_initsem_getvalue ......我预计至少会有一个警告,相反我什至收到代码完成......无论如何,我编辑了原始帖子并进行了一些更正。不确定这是一个真正解决问题的方法,但它似乎有效。检查你们中的一些人是否知道我在帖子末尾添加的问题的答案
  • @Summit Guy:如果他删除了O_EXCL,那么它将打开具有不确定起始值的现有信号量对象。
  • @Saphrosit:您更新的代码对我来说很好(第一次运行)。程序终止后,命名信号量会在内核中持续存在。您需要致电sem_unlink 以完全删除信号量。如果您的程序仅由诸如 Ctrl-C (SIGINT) 之类的信号终止,那么您需要使用signal(2)sigaction(2) 设置一个信号处理程序,该处理程序将在退出前调用sem_unlink

标签: c synchronization posix semaphore


【解决方案1】:

如果你想要两个函数交替使用,你应该只使用一个信号量。

当您的一个线程被调度时,例如 t1,它会锁定 sem1,然后保持它并在一个 while 循环中运行,直到它被中断。因为它没有执行 sem_post(&sem1),所以它不会将控制权交给另一个线程。


更新:再看一遍,这段代码应该可以工作。我认为没有在 OSX 上实现的 sem_init 可能是你的问题。


更新:为了回答您关于 sem_wait 返回 1 的问题,看起来真正的错误值在 errno 中返回。如果返回值!= 0,则检查那里。我在黑暗中的猜测是 EINTR 就是你所看到的。

【讨论】:

  • 完全不确定。当 t1 启动时,它调用sem_wait(&sem1)sem1 被初始化为 1,所以 sem1 的值被设置为 0 并且 t1 进入关键部分(或者简单地传递 sem_wait 调用)。它打印“test1”,然后打印sem_post(&sem2),将sem2 的值设置为1(这样如果t2 在信号量处等待,它可能会进入临界区,否则它会在到达该点时进入)。当 t1 再次开始循环时,它会发现 sem1 变为 0(因为没有 sem_postsem1 上调用),它开始在信号量队列上等待,直到 t2 解锁它。至少在理论上。
猜你喜欢
  • 2013-04-09
  • 1970-01-01
  • 2018-02-06
  • 1970-01-01
  • 2018-03-23
  • 2018-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多