我是C的新手并且学习信号量。我正在尝试使用pthreads,mutex和semaphores来实现一种复杂的餐饮哲学家的情况。
这个想法是,代表服务器的一个信号量将人们安排在两个桌子上(每个4个位置,总共8个)。每个表也由计数信号量控制。每个板都由互斥锁控制,以避免竞争条件。每个人都由一个帖子代表。
我无法理解为什么在我的代码中,同一个客户一直在吃东西,而且似乎没有增加。
代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
sem_t server_sem;
int server_pshared;
int server_ret;
int server_count = 10;
sem_t tablea_sem;
int tablea_pshared;
int tablea_ret;
int tablea_count = 4;
sem_t tableb_sem;
int tableb_pshared;
int tableb_ret;
int tableb_count = 4;
//server_ret = serm_open("serverSem", O_CREAT | O_EXCL, 0644, server_count);
int customer_count = 10;
pthread_t customer[10];
//pthread_t plates[8]
int plate_count = 8;
pthread_mutex_t plates[8];
void *eat(void *i) {
int n = *((int *) i);
pthread_mutex_lock(&plates[n]);
printf("Customer %d is eating\n", n);
sleep(5);
pthread_mutex_unlock(&plates[n]);
printf("Customer %d is finished eating\n", n);
return (NULL);
}
int main() {
server_ret = sem_init(&server_sem, 1, server_count);
tablea_ret = sem_init(&tablea_sem, 1, tablea_count);
tableb_ret = sem_init(&tableb_sem, 1, tableb_count);
//customer = (pthread_t[10] *)malloc(sizeof(customer));
printf ("starting thread, semaphore is unlocked.\n");
int i;
int j;
int k;
for(i=0;i<plate_count;i++) {
pthread_mutex_init(&plates[i],NULL);
printf("Creating mutex for plate %d\n", i);
}
sem_wait(&server_sem);
for (j=0;j<customer_count;j++) {
//pthread_create(&customer[j],NULL,(void *)eat,&j);
if (j<4) {
sem_wait(&tablea_sem);
sem_post(&tableb_sem);
pthread_create(&customer[j],NULL,(void *)eat,&j);
printf("Creating thread for customer %d\n", j);
}
else {
sem_post(&tablea_sem);
sem_wait(&tableb_sem);
pthread_create(&customer[j],NULL,(void *)eat,&j);
printf("Creating thread for customer %d\n", j);
}
}
for(k=0;k<customer_count;k++) {
pthread_join(customer[k],NULL);
printf("Joining thread %d\n", k);
}
for(i=0;i<plate_count;i++) {
pthread_mutex_destroy(&plates[i]);
}
return 0;
}
控制台输出:
starting thread, semaphore is unlocked.
Creating mutex for plate 0
Creating mutex for plate 1
Creating mutex for plate 2
Creating mutex for plate 3
Creating mutex for plate 4
Creating mutex for plate 5
Creating mutex for plate 6
Creating mutex for plate 7
Creating thread for customer 0
Creating thread for customer 1
Creating thread for customer 2
Creating thread for customer 3
Creating thread for customer 4
Creating thread for customer 5
Creating thread for customer 6
Creating thread for customer 7
Creating thread for customer 8
Creating thread for customer 9
Customer 10 is eating
Customer 10 is eating
Customer 10 is eating
Customer 10 is eating
Customer 10 is eating
Customer 10 is eating
Customer 10 is eating
Customer 10 is eating
Customer 10 is eating
Customer 10 is eating
Customer 10 is finished eating
Customer 10 is finished eating
Customer 10 is finished eating
Customer 10 is finished eating
Customer 10 is finished eating
Customer 10 is finished eating
Customer 10 is finished eating
Customer 10 is finished eating
Customer 10 is finished eating
Customer 10 is finished eating
Joining thread 0
Joining thread 1
Joining thread 2
Joining thread 3
Joining thread 4
Joining thread 5
Joining thread 6
Joining thread 7
Joining thread 8
Joining thread 9
编辑:
更新pthread_create的最后一个参数解决了客户增加的问题:
pthread_create(&customer[j],NULL,(void *)eat,(void *) (intptr_t) j);
然而,它从6开始,然后是索引超出范围的问题。
现在控制台输出:
starting thread, semaphore is unlocked.
Creating mutex for plate 0
Creating mutex for plate 1
Creating mutex for plate 2
Creating mutex for plate 3
Creating mutex for plate 4
Creating mutex for plate 5
Creating mutex for plate 6
Creating mutex for plate 7
Creating thread for customer 0
Creating thread for customer 1
Creating thread for customer 2
Creating thread for customer 3
Creating thread for customer 4
Creating thread for customer 5
Creating thread for customer 6
Creating thread for customer 7
Creating thread for customer 8
Creating thread for customer 9
Customer 6 is eating
Customer 7 is eating
Illegal instruction (core dumped)
答案 0 :(得分:3)
使用
行pthread_create(&customer[j],NULL,(void *)eat,&j);
将变量j
的地址作为参数传递给线程。并将相同的地址传递给所有线程的同一个变量。
当循环结束时,j
的值将等于customer_count
,这就是线程可能用作数组索引的内容。它是curseo 超出范围导致未定义的行为。
对于一个可能的解决方案,这实际上是一个接受将整数值转换为指针的地方,然后在线程中将其转换回来。这必须通过几个步骤完成。首先创建线程时:
pthread_create(&customer[j],NULL,(void *)eat, (void *) (intptr_t) j);
然后在线程中:
int n = (int) (intptr_t) i;