【问题标题】:How to create 2 threads which use 1 global variable?如何创建使用 1 个全局变量的 2 个线程?
【发布时间】:2021-12-20 19:55:26
【问题描述】:

我想创建 2 个线程,它们正在使用一个全局变量,我的代码:

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

int var = 0; // 
pthread_t threads[2];

void* function(){
    if(var % 2==0){
        var +=2;
    }
    printf("Addresse %d with var %d\n", &var, var);
}

int main() {

    for(int i = 0; i < 2; i++){
        pthread_create(&threads[i], NULL, &function, NULL);
    }
    pthread_exit(NULL);
}

我用 for 循环创建了 2 个线程。我想让两个线程都使用全局变量。一个线程增加 2,另一个线程增加 2。我用 printf 看到,它们都使用相同的地址,但输出不同。如何让每个线程执行不同的任务?

【问题讨论】:

    标签: c linux multithreading pthreads global-variables


    【解决方案1】:

    您应该参考What is a race condition?。这是多线程竞争条件的经典示例,其中两个线程正在读取和写入相同的内存地址。

    编辑:您还将作为起点的相同函数传递给两个线程。它们都检查值是否为偶数,如果是,则将值加二。

    如果您希望一个线程相加,另一个线程相乘,那么您可以使用两个函数(我也在使用 mevets 推荐用于同步的互斥变量)。无论哪种方式,您的代码都将是不确定的

        void* add(){
           int val;
           pthread_mutex_lock(&varlock);
           if(var % 2==0){
               var +=2;
           }
           val = var;
           pthread_mutex_unlock(&varlock);
           printf("Addresse %d with var %d\n", &var, val);
        }
     
        void* multiply(){
            int val;
            pthread_mutex_lock(&varlock);
            if(var % 2==0){
                var *=2;
            }
            val = var;
            pthread_mutex_unlock(&varlock);
            printf("Addresse %d with var %d\n", &var, val);
        }
    
    
    int main(){
       pthread_create(&threads[0], NULL, &add, NULL);
       pthread_create(&threads[1], NULL, &multiply, NULL);
       pthread_exit(NULL);
    }
    

    每次运行此代码时,您可能会得到不同的输出,因为它是不确定的。

    【讨论】:

    • 在for循环还是函数中加2更好?
    • 你想用这段代码完成什么?如果您只是想执行 x 次,请在单个线程中使用 for 循环。如果您正在尝试学习线程,那么您应该从阅读并发以及线程如何共享内存空间开始。重读这个问题后,我似乎误解了你在问什么。您是否希望这两个函数都输出2
    • 我想创建 2 个使用 1 个全局变量的线程。我希望两者都做不同的操作,比如 1. 一个做加法,2. 一个做乘法
    【解决方案2】:

    如何让每个线程执行不同的任务?

    一种方法是为每个线程编写一个单独的线程函数。在这种情况下,通过自己的 pthread_create() 调用而不是使用循环来启动每个函数会更容易。

    如果您必须使用相同的线程函数,但又希望它在两种情况下执行不同的工作,那么最简单的做法是使用线程函数的参数(您的代码未能声明该参数)。例如:

    void *function(void *arg) {
        if ((intptr_t) arg == 0) {
            // do one thing ...
        } else {
            // do a different thing ...
        }
        return /* something */;
    }
    
    int main(void) {
        // ...
        for(intptr_t i = 0; i < 2; i++) {
            pthread_create(&threads[i], NULL, &function, (void *) i);
        }
        // ...
    }
    

    另请注意,但是,如果您的线程都访问同一个非原子全局变量,并且其中至少有一个修改了它,那么您必须同步它们的访问,以便它们无法访问它同时。有几种方法可以做到这一点,但最常规的是提供一个互斥锁,每个线程在访问变量之前锁定并在之后解锁。

    【讨论】:

      【解决方案3】:

      在多个线程之间安全共享变量的最简单方法是使用互斥锁(互斥)。我修改了您的程序以使用一个。请注意,它锁定了检查和修改变量的区域。虽然互斥锁对于此类应用程序很简单,但其他可能涉及等待var 具有特定值的应用程序将需要条件变量(pthread_cond_t)之类的东西。这是满足不同需求的丰富选择;但这应该让你开始:

      #include <stdio.h>
      #include <pthread.h>
      #include <stdlib.h>
      #include <unistd.h>
      
      int var = 0; // 
      pthread_mutex_t varlock = PTHREAD_MUTEX_INITIALIZER;
      #define NTH 20
      pthread_t threads[NTH];
      
      void* function(){
          int val;
          pthread_mutex_lock(&varlock);
          if(var % 2==0){
              var +=2;
          }
          val = var;
          pthread_mutex_unlock(&varlock);
          printf("Addresse %d with var %d\n", &var, val);
      }
      
      int main() {
      
          for(int i = 0; i < NTH; i++){
              pthread_create(&threads[i], NULL, &function, NULL);
          }
          pthread_exit(NULL);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-07-12
        • 1970-01-01
        • 2013-02-12
        • 1970-01-01
        • 1970-01-01
        • 2021-12-18
        • 2017-08-10
        • 1970-01-01
        相关资源
        最近更新 更多