2017-10-06 86 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至於崩潰,您需要使用調試器來找到它。如果你不能在調試器的幫助下弄清楚它,可能會問一個關於它的新問題。 –