我写了一个简单的程序,使用信号量解决了Readers-Writers问题。它在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
...
答案 0 :(得分:13)
检查sem_init调用的错误返回;我打赌你会发现OS X版本返回“功能未实现”错误。
这是因为unnamed POSIX semaphores are not implemented on OS X。您需要使用命名信号量或pthread互斥/条件变量。
答案 1 :(得分:2)
为了完整起见,这是一个使用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);
}
}