使用信号量的程序在 Linux 上运行良好...在 Mac osX 上出现意外结果

发布于 2024-10-01 17:57:55 字数 1816 浏览 1 评论 0原文

我编写了一个简单的程序,使用信号量解决读写器问题。它在 Linux 操作系统上完美运行,但是当我在 Mac osX 上运行它时,我得到了意想不到的结果,但我不明白为什么。

我的程序:

#include <semaphore.h>
#include <sys/types.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void* function1(void* val);
void* function2(void* val);

// shared values
volatile int X;
volatile int Y;

// declare semaphores
sem_t s1;
sem_t s2;

main()
{
void* status;

pthread_t thread1;
pthread_t thread2;
srand(time(NULL));

// initialize semaphores to zero
sem_init(&s1, 0, 0);
sem_init(&s2, 0, 0);

pthread_create(&thread1, NULL, function1, NULL);
pthread_create(&thread2, NULL, function2, NULL);

pthread_join(thread1, &status);
pthread_join(thread2, &status);

sem_destroy(&s1);
sem_destroy(&s2);

}

void* function1(void* val)
{
   while(1)
   {
   X = rand()%1000; // write 
   printf("After thread ID A writes to X, X = %d\n", X);
   sem_post(&s1); // signal
   sem_wait(&s2); // wait
   printf("After thread ID A reads from Y, Y = %d\n", Y); // read
   sleep(3);
   }   
}

void* function2(void* val)
{
   while(1)
   {
    sem_wait(&s1); // wait
    printf("After thread ID B reads from X, X = %d\n", X); // read
    Y = rand()%1000; // write
    printf("After thread ID B write to Y, Y = %d\n", Y);
    sem_post(&s2); // signal
    sleep(3);
   }
}

我在 Linux 上收到的输出(应该是什么样子):

After thread ID A writes to X, X = 100
After thread ID B reads from X, X = 100
After thread ID B write to Y, Y = 234
After thread ID A reads from Y, Y = 234
...

Mac osX 上的输出(意外):

After thread ID A writes to X, X = 253
After thread ID A reads from Y, Y = 0
After thread ID B reads from X, X = 253
After thread ID B write to Y, Y = 728
...

I wrote a simple program solving the Readers-Writers problem using semaphores. It runs perfectly on Linux os, but when I run it on my Mac osX I get unexpected results and I can't figure out why.

My Program:

#include <semaphore.h>
#include <sys/types.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void* function1(void* val);
void* function2(void* val);

// shared values
volatile int X;
volatile int Y;

// declare semaphores
sem_t s1;
sem_t s2;

main()
{
void* status;

pthread_t thread1;
pthread_t thread2;
srand(time(NULL));

// initialize semaphores to zero
sem_init(&s1, 0, 0);
sem_init(&s2, 0, 0);

pthread_create(&thread1, NULL, function1, NULL);
pthread_create(&thread2, NULL, function2, NULL);

pthread_join(thread1, &status);
pthread_join(thread2, &status);

sem_destroy(&s1);
sem_destroy(&s2);

}

void* function1(void* val)
{
   while(1)
   {
   X = rand()%1000; // write 
   printf("After thread ID A writes to X, X = %d\n", X);
   sem_post(&s1); // signal
   sem_wait(&s2); // wait
   printf("After thread ID A reads from Y, Y = %d\n", Y); // read
   sleep(3);
   }   
}

void* function2(void* val)
{
   while(1)
   {
    sem_wait(&s1); // wait
    printf("After thread ID B reads from X, X = %d\n", X); // read
    Y = rand()%1000; // write
    printf("After thread ID B write to Y, Y = %d\n", Y);
    sem_post(&s2); // signal
    sleep(3);
   }
}

The output I receive on Linux (what it's supposed to look like):

After thread ID A writes to X, X = 100
After thread ID B reads from X, X = 100
After thread ID B write to Y, Y = 234
After thread ID A reads from Y, Y = 234
...

The output on Mac osX (unexpected):

After thread ID A writes to X, X = 253
After thread ID A reads from Y, Y = 0
After thread ID B reads from X, X = 253
After thread ID B write to Y, Y = 728
...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

奶茶白久 2024-10-08 17:57:55

检查 sem_init 调用的错误返回;我打赌您会发现 OS X 版本返回“功能未实现”错误。

这是因为 OS X 上未实现未命名的 POSIX 信号量。您需要使用命名信号量或 pthread 互斥/条件变量。

Check the error return on the sem_init calls; I bet you'll find the OS X version returning a "Function not implemented" error.

This is because unnamed POSIX semaphores are not implemented on OS X. You need to use named semaphores, or pthread mutex/condition variables.

如歌彻婉言 2024-10-08 17:57:55

为了完整起见,这里是一个使用 sem_open()sem_unlink() 而不是 sem_init()sem_destroy 的 Mac OS X 版本()

/*
cat semtest.c

source:
"Program using Semaphores runs fine on Linux...unexpected results on Mac osX",
http://stackoverflow.com/questions/4136181/program-using-semaphores-runs-fine-on-linux-unexpected-results-on-mac-osx

compiled on Mac OS X 10.6.8 with:
gcc -ansi -pedantic -std=gnu99 -Os -Wall -Wextra -Wshadow -l pthread -o semtest semtest.c

./semtest

*/


#include <semaphore.h>
#include <sys/types.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>

void* function1();
void* function2();

// shared values
volatile int X;
volatile int Y;

// declare semaphores
//sem_t s1;
//sem_t s2;
sem_t *s1;
sem_t *s2;
static const char *semname1 = "Semaphore1";
static const char *semname2 = "Semaphore2";

int main(void)
{

   void* status;

   pthread_t thread1;
   pthread_t thread2;
   srand(time(NULL));

   /*
   // initialize semaphores to zero
   sem_init(&s1, 0, 0);
   sem_init(&s2, 0, 0);
   */

   s1 = sem_open(semname1, O_CREAT, 0777, 0);
   if (s1 == SEM_FAILED)
   {
      fprintf(stderr, "%s\n", "ERROR creating semaphore semname1");
      exit(EXIT_FAILURE);
   }

   s2 = sem_open(semname2, O_CREAT, 0777, 0);
   if (s2 == SEM_FAILED)
   {
      fprintf(stderr, "%s\n", "ERROR creating semaphore semname2");
      exit(EXIT_FAILURE);
   }


   pthread_create(&thread1, NULL, function1, NULL);
   pthread_create(&thread2, NULL, function2, NULL);

   pthread_join(thread1, &status);
   pthread_join(thread2, &status);

   //sem_destroy(&s1);
   //sem_destroy(&s2);
   sem_unlink(semname1);
   sem_unlink(semname2);

   return 0;

}

void* function1()
{
   while(1)
   {
   X = rand()%1000; // write 
   printf("After thread ID A writes to X, X = %d\n", X);
   //sem_post(&s1); // signal
   //sem_wait(&s2); // wait
   sem_post(s1); // signal
   sem_wait(s2); // wait
   printf("After thread ID A reads from Y, Y = %d\n", Y); // read
   sleep(3);
   }   
}

void* function2()
{
   while(1)
   {
    //sem_wait(&s1); // wait
    sem_wait(s1); // wait
    printf("After thread ID B reads from X, X = %d\n", X); // read
    Y = rand()%1000; // write
    printf("After thread ID B write to Y, Y = %d\n", Y);
    //sem_post(&s2); // signal
    sem_post(s2); // signal
    sleep(3);
   }
}

Just for completeness, here's a working Mac OS X version using sem_open() and sem_unlink() instead of sem_init() and sem_destroy().

/*
cat semtest.c

source:
"Program using Semaphores runs fine on Linux...unexpected results on Mac osX",
http://stackoverflow.com/questions/4136181/program-using-semaphores-runs-fine-on-linux-unexpected-results-on-mac-osx

compiled on Mac OS X 10.6.8 with:
gcc -ansi -pedantic -std=gnu99 -Os -Wall -Wextra -Wshadow -l pthread -o semtest semtest.c

./semtest

*/


#include <semaphore.h>
#include <sys/types.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>

void* function1();
void* function2();

// shared values
volatile int X;
volatile int Y;

// declare semaphores
//sem_t s1;
//sem_t s2;
sem_t *s1;
sem_t *s2;
static const char *semname1 = "Semaphore1";
static const char *semname2 = "Semaphore2";

int main(void)
{

   void* status;

   pthread_t thread1;
   pthread_t thread2;
   srand(time(NULL));

   /*
   // initialize semaphores to zero
   sem_init(&s1, 0, 0);
   sem_init(&s2, 0, 0);
   */

   s1 = sem_open(semname1, O_CREAT, 0777, 0);
   if (s1 == SEM_FAILED)
   {
      fprintf(stderr, "%s\n", "ERROR creating semaphore semname1");
      exit(EXIT_FAILURE);
   }

   s2 = sem_open(semname2, O_CREAT, 0777, 0);
   if (s2 == SEM_FAILED)
   {
      fprintf(stderr, "%s\n", "ERROR creating semaphore semname2");
      exit(EXIT_FAILURE);
   }


   pthread_create(&thread1, NULL, function1, NULL);
   pthread_create(&thread2, NULL, function2, NULL);

   pthread_join(thread1, &status);
   pthread_join(thread2, &status);

   //sem_destroy(&s1);
   //sem_destroy(&s2);
   sem_unlink(semname1);
   sem_unlink(semname2);

   return 0;

}

void* function1()
{
   while(1)
   {
   X = rand()%1000; // write 
   printf("After thread ID A writes to X, X = %d\n", X);
   //sem_post(&s1); // signal
   //sem_wait(&s2); // wait
   sem_post(s1); // signal
   sem_wait(s2); // wait
   printf("After thread ID A reads from Y, Y = %d\n", Y); // read
   sleep(3);
   }   
}

void* function2()
{
   while(1)
   {
    //sem_wait(&s1); // wait
    sem_wait(s1); // wait
    printf("After thread ID B reads from X, X = %d\n", X); // read
    Y = rand()%1000; // write
    printf("After thread ID B write to Y, Y = %d\n", Y);
    //sem_post(&s2); // signal
    sem_post(s2); // signal
    sleep(3);
   }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文