2012-06-29 67 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的最终值之前,请使用屏障来等待所有线程完成其工作。