【问题标题】:Thread sync by using mutex and barrier in C在 C 中使用互斥锁和屏障进行线程同步
【发布时间】:2012-06-30 13:56:52
【问题描述】:

我正在尝试使用 pthread 互斥变量和屏障来同步我的程序的输出,但它没有按照我想要的方式工作。每个线程每 20 个值(来自 for 循环)看到它的最终值,这没关系,但我试图让它们都达到相同的最终值(如果使用 5 个线程,它们都应该看到 100 作为最终值,有 4 个线程,80 个等)

#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);
}

非常感谢任何建议或帮助! 提前致谢!

【问题讨论】:

    标签: c synchronization pthreads mutex barrier


    【解决方案1】:

    您需要在检查最终值之前使用屏障 (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;
    }
    

    【讨论】:

    • 当它读取 argv[1] 并以数字开头时,它将读取第一个数字并忽略其余部分,例如“3sdfsdf”将创建 3 个线程。关于如何解决这个问题的任何想法?
    • @fgualda87:使用strtol() 而不是atoi() - 它会告诉您转换后的数字后的第一个字符,您可以使用它来查看整个字符串是否有效。如果这还不够清楚,请作为另一个问题提出。
    【解决方案2】:

    尝试将pthread_mutext_unlock(&amp;mutext1) 移出SimpleThread 中的for 循环。您在原始代码中锁定一次并解锁多次(20)次。

    或者,您可以将 pthread_mutex_lock(&amp;mutext1) 移动到 for 循环中,就在您阅读和修改您的 SharedVariable 之前。在这种情况下,每个线程的add-by-one操作可能不连续,但每个线程都会得到正确的最终值。

    在读取SharedVariable 的最终值之前,请使用屏障等待所有线程完成它们的工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-06
      • 2014-05-02
      • 1970-01-01
      • 2020-12-07
      • 1970-01-01
      • 1970-01-01
      • 2014-09-11
      • 1970-01-01
      相关资源
      最近更新 更多