2012-06-29 96 views
0

我正在嘗試使用pthread互斥變量和屏障來同步我的程序的輸出,但它並不按我希望的方式工作。每個線程都會看到每20個值的最終值(來自for循環),但是我試圖讓它們都達到相同的最終值(如果使用5個線程,它們都應該看到100個爲最終值,4線程,80等)通過在C中使用互斥鎖和屏障進行線程同步

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

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; 

int SharedVariable =0; 
void *SimpleThread(void *args) 
{ 
    int num,val,rc; 
    int which =(int)args; 
    rc = pthread_mutex_lock(&mutex1); 
    for(num=0; num<20; num++){ 
#ifdef PTHREAD_SYNC 
     if(random() > RAND_MAX/2) 
      usleep(10); 
#endif 
     //pthread_mutex_lock(&mutex1); 
     val = SharedVariable; 
     printf("*** thread %d sees value %d\n", which, val); 
     //pthread_mutex_lock(&mutex1); 
     SharedVariable = val+1; 
     pthread_mutex_unlock(&mutex1); 
    } 
    val=SharedVariable; 

    printf("Thread %d sees final value %d\n", which, val); 
    //pthread_mutex_destroy(&mutex1); 
    //pthread_exit((void*) 0); 
    //pthread_mutex_unlock(&mutex1); 

} 

int main (int argc, char *argv[]) 
{ 
    if(atoi(argv[1]) > 0){   
    int num_threads = atoi(argv[1]); 
    //pthread_mutex_init(&mutex1, NULL); 
    pthread_t threads[num_threads]; 
    int rc; 
    long t; 
    rc = pthread_mutex_lock(&mutex1); 
    for(t=0; t< num_threads; t++){ 
     printf("In main: creating thread %ld\n", t); 
     rc = pthread_create(&threads[t], NULL, SimpleThread, (void*)t); 
     if (rc){ 
     printf("ERROR; return code from pthread_create() is %d\n", rc); 
     exit(-1); 
     } 

    //pthread_join(thread1); 

    } 
    rc= pthread_mutex_unlock(&mutex1); 
} 
    else{ 
     printf("ERROR: The parameter should be a valid positive number."); 
     exit(-1); 
    } 

    pthread_mutex_destroy(&mutex1); 
    pthread_exit(NULL); 
} 

任何建議或幫助,非常感謝! 感謝先進!

回答

2

在檢查最終值之前,您需要使用屏障(pthread_barrier_wait()) - 這可確保在所有線程都到達屏障之前不會進行線程處理。

此外,你應該打電話pthread_join()等待線程完成,你只需要按住周圍的增量互斥:

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

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; 
pthread_barrier_t barrier1; 

int SharedVariable = 0; 

void *SimpleThread(void *args) 
{ 
    int num,val; 
    int which = (int)args; 

    for(num = 0; num < 20; num++) { 
#ifdef PTHREAD_SYNC 
     if(random() > RAND_MAX/2) 
      usleep(10); 
#endif 
     pthread_mutex_lock(&mutex1); 
     val = SharedVariable; 
     printf("*** thread %d sees value %d\n", which, val); 
     SharedVariable = val + 1; 
     pthread_mutex_unlock(&mutex1); 
    } 

    pthread_barrier_wait(&barrier1); 

    val = SharedVariable; 
    printf("Thread %d sees final value %d\n", which, val); 
    return 0; 
} 

int main (int argc, char *argv[]) 
{ 
    int num_threads = argc > 1 ? atoi(argv[1]) : 0; 

    if (num_threads > 0) { 
     pthread_t threads[num_threads]; 
     int rc; 
     long t; 

     rc = pthread_barrier_init(&barrier1, NULL, num_threads); 

     if (rc) { 
      fprintf(stderr, "pthread_barrier_init: %s\n", strerror(rc)); 
      exit(1); 
     } 

     for (t = 0; t < num_threads; t++) { 
      printf("In main: creating thread %ld\n", t); 
      rc = pthread_create(&threads[t], NULL, SimpleThread, (void*)t); 
      if (rc) { 
       printf("ERROR; return code from pthread_create() is %d\n", rc); 
       exit(-1); 
      } 
     } 

     for (t = 0; t < num_threads; t++) { 
      pthread_join(threads[t], NULL); 
     } 
    } 
    else { 
     printf("ERROR: The parameter should be a valid positive number.\n"); 
     exit(-1); 
    } 

    return 0; 
} 
+0

時,它讀取的argv [1],並與開始一個數字會讀取第一個數字並忽略其餘數字,如「3sdfsdf」將創建3個線程。任何想法如何解決這個問題? – randomizertech

+0

@ fgualda87:使用'strtol()'而不是'atoi()' - 它會告訴你轉換後的數字後面的第一個字符,你可以用它來查看整個字符串是否有效。如果這不夠清楚,請將此作爲另一個問題。 – caf

1

嘗試將pthread_mutext_unlock(&mutext1)移出SimpleThread中的for循環。您鎖定一次,並在原始代碼中解鎖多次(20)次。

或者,您可以將pthread_mutex_lock(&mutext1)移動到for循環中,就在您閱讀和修改您的SharedVariable之前。在這種情況下,每個線程的add-by-one操作可能不會連續,但每個線程都會得到正確的最終值。

並且在您讀取SharedVariable的最終值之前,請使用屏障來等待所有線程完成其工作。