【问题标题】:Scheduling two threads in linux two print a pattern of numbers在linux中调度两个线程两个打印一个数字模式
【发布时间】:2016-10-17 06:18:35
【问题描述】:

我想使用两个线程 T1T2 打印数字。 T1 应该打印像1,2,3,4,5 这样的数字,然后T2 应该打印6,7,8,9,10,然后T1 应该开始,然后T2 应该跟随。它应该从1....100 打印。我有两个问题。

  1. 如何使用线程和一个全局变量完成任务?
  2. 如何在 linux 中按所需顺序调度线程?

【问题讨论】:

标签: c linux multithreading synchronization


【解决方案1】:

如何在 linux 中按所需顺序调度线程?

您需要使用锁定原语,例如互斥锁或条件变量来影响线程的调度顺序。或者你必须让你的线程在订单上独立工作。

如何使用线程和一个全局变量完成任务?

如果您只允许使用一个变量,那么您不能使用互斥锁(它将是第二个变量)。所以你必须做的第一件事就是声明你的变量是原子的。否则编译器可能会优化你的代码,使得一个线程不会看到其他线程所做的更改。对于您想要的如此简单的代码,它将通过在寄存器上缓存变量来实现。使用std::atomic_int。您可能会找到使用volatile int 的建议,但现在std::atomic_int 是一种更直接的方法来指定您想要的内容。

你不能使用互斥锁,所以你不能让你的线程等待。它们将不断运行并浪费 CPU。但这对于这项任务来说似乎没问题。所以你需要写一个自旋锁。线程将在一个循环中等待,不断检查该值。如果value % 10 < 5 则第一个线程中断循环并执行递增,否则第二个线程执行此工作。

因为这个问题看起来像一个家庭作业,所以我没有在这里展示任何代码示例,你需要自己编写它们。

【讨论】:

    【解决方案2】:

    1:最简单的方法是使用互斥锁。 这是一个带有不公平/未定义调度的基本实现

    int counter=1;
    pthread_mutex_t mutex; //needs to be initialised
    
    void incrementGlobal() {
        for(int i=0;i<5;i++){
            counter++;
            printf("%i\n",counter);
        }
     }
    

    T1/T2:

    pthread_mutex_lock(&mutex);
    incrementGlobal();
    pthread_mutex_unlock(&mutex);
    

    2:可以使用条件变量来归档正确的顺序: (但这需要更多的全局变量)

    全局:

    int num_thread=2;
    int current_thread_id=0;
    pthread_cond_t cond; //needs to be initialised
    

    T1/T2:

    int local_thread_id; // the ID of the thread
    while(true) {
        phread_mutex_lock(&mutex);
        while (current_thread_id != local_thread_id) {
            pthread_cond_wait(&cond, &mutex);
        }
        incrementGlobal();
        current_thread_id = (current_thread_id+1) % num_threads; 
        pthread_cond_broadcast(&cond);
        pthread_mutex_unlock(&mutex);
    }
    

    【讨论】:

      【解决方案3】:

      如何使用线程和一个全局变量完成任务?

      如果您使用Linux,您可以使用POSIX 库在C 编程语言中进行线程化。图书馆是&lt;pthread.h&gt;。然而,作为替代方案,一个非常便携且相对非侵入性的库,在gccg++ 上得到很好的支持,MSVC 上的(旧版本)是openMP

      它不是标准的 C 和 C++,但 OpenMP 本身就是一个标准。

      如何在 linux 中按所需顺序调度线程?

      为了实现你想要的打印操作,你需要一个全局变量,它可以被你的两个线程访问。两个线程轮流访问全局变量variable并执行操作(incrementprint)。但是,要实现desired order,您需要有一个mutex。互斥量是一种互斥信号量,是信号量的一种特殊变体,一次只允许一个储物柜。当您有一个资源实例 (global variable in your case) 并且该资源由两个线程共享时,可以使用它。锁定该互斥锁后的线程可以独占访问资源实例,并且在完成其操作后,线程应该为其他线程释放互斥锁。

      您可以从here 中的&lt;pthread.h&gt; 中的线程和互斥锁开始。

      您的问题可能的解决方案之一可能是该程序如下所示。不过,我建议你自己找试试看,然后看看我的解决方案。

      #include <stdio.h>
      #include <pthread.h>
      #include <unistd.h>
      
      pthread_mutex_t lock;
      int variable=0;
      
      #define ONE_TIME_INC 5
      #define MAX 100
      
      void *thread1(void *arg)
      {
       while (1) {
          pthread_mutex_lock(&lock);
          printf("Thread1: \n");
          int i;
          for (i=0; i<ONE_TIME_INC; i++) {
              if (variable >= MAX)
                  goto RETURN;
              printf("\t\t%d\n", ++variable);
          }   
          printf("Thread1: Sleeping\n");
          pthread_mutex_unlock(&lock);
          usleep(1000);
      }
      RETURN:
      pthread_mutex_unlock(&lock);
      return NULL;
      }
      
      void *thread2(void *arg)
      {
      while (1) {
          pthread_mutex_lock(&lock);
          printf("Thread2: \n");
          int i;
          for (i=0; i<ONE_TIME_INC; i++) {
              if (variable >= MAX)
                  goto RETURN;
              printf("%d\n", ++variable);
          }   
          printf("Thread2: Sleeping\n");
          pthread_mutex_unlock(&lock);
          usleep(1000);
      }
      RETURN:
      pthread_mutex_unlock(&lock);
      return NULL;
      
      }
      
      int main()
      {
      
      if (pthread_mutex_init(&lock, NULL) != 0) {
          printf("\n mutex init failed\n");
          return 1;
      }
      
      pthread_t pthread1, pthread2;
      if (pthread_create(&pthread1, NULL, thread1, NULL))
          return -1;
      if (pthread_create(&pthread2, NULL, thread2, NULL))
          return -1;
      
      pthread_join(pthread1, NULL);
      pthread_join(pthread2, NULL);
      
      pthread_mutex_destroy(&lock);
      
      return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-25
        • 2015-04-25
        • 2022-01-19
        • 2012-11-13
        • 2018-12-28
        相关资源
        最近更新 更多