2017-10-06 83 views
0

我是C新手,学习信号量。我试图用pthreads,mutex和信号量来实现一种复杂的餐饮哲学家的情况。意外的pthread函数输出

这个想法是,一个信号量代表一个服务器,在两个表(每个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) 

回答

3

随着线

pthread_create(&customer[j],NULL,(void *)eat,&j); 

你的变量j的地址传递给线程作为参数。并且您将相同的地址传递给相同的变量全部线程。

当循环结束时,j的值将等于customer_count,这就是线程可能用作数组中的索引。并且它的诅咒出界导致未定义的行为

至于一个可能的解决方案,这实际上是一个地方,它接受将一个整型值转换为一个指针,然后在线程中将其转换回来。尽管这需要经过几个步骤才能完成。在线程本身

pthread_create(&customer[j],NULL,(void *)eat, (void *) (intptr_t) j); 

然后:首先创建线程时

int n = (int) (intptr_t) i; 
+0

这做的伎俩 - 但它在6开始编辑了一下我的问题,如果你有这种洞察力。 – user25976

+1

@ user25976线程运行的顺序不确定。操作系统可以按照它认为合适的顺序运行它们。 –

+1

@ user25976至于崩溃,您需要使用调试器来找到它。如果你不能在调试器的帮助下弄清楚它,可能会问一个关于它的新问题。 –