2017-03-08 33 views
0

我在程序中創建了5個線程,並分別爲它們分配了ID 1,2,3,4,5。每個線程都會嘗試訪問Next_ID。當一個線程獲取Next_ID時,它會將其ID與Next_ID進行比較。如果它匹配我打印輪到我打開而其他打印不輪到我。並遞增1 NEXT_ID如果NEXT_ID達到6將其重置回1。但是我的代碼打印如下:編程線程

My Turn: 1 
Not My Turn: 3 
My Turn: 4 
My Turn: 5 
Not My Turn: 2 
Not My Turn: 1 
Not My Turn: 3 
My Turn: 4 
My Turn: 5 
Not My Turn: 2 
Not My Turn: 1 
Not My Turn: 3 
My Turn: 4 
My Turn: 5 
Not My Turn: 2 
Not My Turn: 1 
Not My Turn: 3 
My Turn: 4 
My Turn: 5 
Not My Turn: 2 
Not My Turn: 1 
Not My Turn: 3 
My Turn: 4 
My Turn: 5 

預期的輸出應該是:

My Turn: 1 
not my Turn: 2 
not my Turn: 3 
not my Turn: 4 
not my Turn: 5 
not my Turn: 1 
My Turn: 2 
not my Turn: 3 
not my Turn: 4 
not my Turn: 5 

我的代碼:

#include <stdio.h> 
#include <pthread.h> 
#include <stdlib.h> 
#include <unistd.h> 

#define NUM_THREADS 5 

int Next_ID = 1; 

pthread_t threads[NUM_THREADS]; 
pthread_mutex_t mutex; 

typedef struct threadArgs { 
    int threadId; 
    int numOfCalls; 
} ThreadArgs; 

ThreadArgs threadArgsArray[NUM_THREADS]; 

void * printThread(void *pThreadArgs) { 
    ThreadArgs *threadArgs = (ThreadArgs *) pThreadArgs; 
    int *threadId = &threadArgs->threadId; 

    for(int i = 0; i < 20; i++) { 
     pthread_mutex_lock(&mutex); 
     if (Next_ID == *threadID) { 
      printf("My Turn: %d\n", *threadId); 
     } else { 
      printf("Not My Turn: %d\n", *threadId); 
     } 

     Next_ID = (*threadId == 5) ? 1 : *threadId + 1; 
     pthread_mutex_unlock (&mutex); 
    } 
    pthread_exit(NULL); 
} 


void * printThread(void *); 

int main(int argc, char const *argv[]) { 
    pthread_attr_t attr; 
    void *status; 

    pthread_mutex_init(&mutex, NULL); 
    pthread_attr_init(&attr); 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 
    for (int i = 0; i < NUM_THREADS; i++) { 
     threadArgsArray[i].threadId = i + 1; 

     int rc = pthread_create(&threads[i], &attr, printThread, 
           &threadArgsArray[i]); 
    } 

    for (int i = 0; i < NUM_THREADS; i++) { 
     int rc = pthread_join(threads[i], &status); 
    } 

    pthread_attr_destroy(&attr); 
    pthread_mutex_destroy(&mutex); 

    pthread_exit(NULL); 
} 
+0

你肯定是你的真實和精確的輸出?它看起來太經常而不真實,並且看起來不符合您所看到的代碼的行爲方式。 – kaylum

+2

這樣比較好。原因是因爲你的假設是錯誤的。你的代碼中沒有任何東西可以保證線程2會在線程1之後立即執行,等等。也就是說,你有互斥,但你沒有排序。 – kaylum

+0

我該怎麼做? – user456

回答

0

爲了順序地從線程1運行到線程5,可以使用conditional variablepthread_cond_t)。變量current來指定哪個線程可以運行。

另一個明顯的做法,是使用pipe。下面

代碼使用conditional variable

#include <stdio.h> 
#include <pthread.h> 
#include <stdlib.h> 
#include <unistd.h> 

#define NUM_THREADS 5 

int Next_ID = 1; 

pthread_t threads[NUM_THREADS]; 
pthread_mutex_t mutex; 
pthread_cond_t cond; 
int current; 

typedef struct threadArgs { 
    int threadId; 
    int numOfCalls; 
} ThreadArgs; 

ThreadArgs threadArgsArray[NUM_THREADS]; 

void * printThread(void *pThreadArgs) { 
    ThreadArgs *threadArgs = (ThreadArgs *) pThreadArgs; 
    int *threadId = &threadArgs->threadId; 

    for(int i = 0; i < 20; i++) { 
     pthread_mutex_lock(&mutex); 
     while (current+1!=*threadId){ 
      pthread_cond_wait(&cond, &mutex); 
     } 
     if (Next_ID == *threadId) { 
      printf("My Turn: %d\n", *threadId); 
     } else { 
      printf("Not My Turn: %d\n", *threadId); 
     } 

     if (*threadId==5){ 
      Next_ID++; 
      if (Next_ID==6){ 
       Next_ID=1; 
      } 
     } 
     current=(current+1)%NUM_THREADS; 
     pthread_cond_broadcast(&cond); 
     pthread_mutex_unlock(&mutex); 
    } 
    pthread_exit(NULL); 
} 


void * printThread(void *); 

int main(int argc, char const *argv[]) { 
    pthread_attr_t attr; 
    void *status; 

    pthread_mutex_init(&mutex, NULL); 
    pthread_cond_init(&cond, NULL); 
    pthread_attr_init(&attr); 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 
    current=0; 
    for (int i = 0; i < NUM_THREADS; i++) { 
     threadArgsArray[i].threadId = i + 1; 

     int rc = pthread_create(&threads[i], &attr, printThread, 
        &threadArgsArray[i]); 
    } 

    for (int i = 0; i < NUM_THREADS; i++) { 
     int rc = pthread_join(threads[i], &status); 
    } 

    pthread_attr_destroy(&attr); 
    pthread_mutex_destroy(&mutex); 

    pthread_exit(NULL); 
}