在pthread中醒来单个线程,而不是忙等待的 [英] Waking up individual threads instead of busy wait in pthreads

查看:248
本文介绍了在pthread中醒来单个线程,而不是忙等待的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不知道如果标题反映了我在问什么在这里但这就是最好没有一个非常龙头衔,我可以做的。在的pthreads我试图实施工作线程模式。我想产卵从函数一组线程,其后线程代表工作的工人,等待所有线程分配它们的下一个作业之前完成(实际上,要求是安排很像CUDA编程模型,但在CPU中的块的线程。虽然它不是当前问题相关)。在工作阵列用于指示作业的每个线程的类型。目前,我实现了这一点使用信号灯其中规定忙等待。我在寻找各种方法来让这个线程去睡觉,醒来时只需要他们,而不是不断地轮询

I'm not sure if the title reflects what I'm asking here but thats best I can do without a very loong title. I'm trying to implement a worker thread model in pthreads. I want to spawn a set of threads from the main function and thereafter the main thread delegates the job to the worker and wait for all threads to complete before assigning them the next job (Actually, the requirement is to arrange the thread in a block much like CUDA programming model but on the CPU. Although its not relevant to the current question). The job array is used to indicate the type of job to each thread. Currently, I've implemented this using semaphores which imposes a busy wait. I'm looking for ways to make it so that the threads go to sleep and wake up only when they are required rather than polling continuously.

每个线程执行的功能。

volatile int jobs[MAX_THREADS]; // global job indicator array
sem_t semaphore;                // semaphore to indicate completion
thread_execute(void *args)
{
  tid = get_id(args);
  while(jobs[tid] != -1)
  {
    if(jobs[tid] == 0) continue; // no job
    if(jobs[tid] == JOBS_1)
    {
      jobs1();
      jobs[tid] = 0; // go back to idle state
      sem_post(&semapahore);
    }
    if(jobs[tid] == JOBS_2)
    {
      jobs2();
      jobs[tid] = 0; // go back to idle state
      sem_post(&semapahore);
    }
  }

  pthread_exit(NULL);
}

主要功能如下:

int main()
{
  sem_init(&semaphore, 0, 0);
  jobs[0...MAX_THREADS] = 0;
  spawn_threads();

  // Dispatch first job
  jobs[0...MAX_THREADS] = JOBS_1;
  int semvalue = 0;
  while (semvalue < MAX_THREADS) // Wait till all threads increment the semaphore
    sem_getvalue(&sempaphore, &semvalue);

  sem_init(&semaphore, 0, 0); // Init semaphore back to 0 for the next job
                              // I'm actually using diff. semaphores for diff. jobs
  jobs[0...MAX_THREADS] = JOBS_2;
  while (semvalue < MAX_THREADS)
    sem_getvalue(&sempaphore, &semvalue);

  jobs[0...MAX_THREADS] = -1; // No more jobs
  pthread_join();
}

这个实现的问题是,线程繁忙等待所有工作线程来完成和工作线程也在不断轮询作业阵列检查新工作。有没有更好的办法做到这一点时,线程进入睡眠状态,并沿着葛处理程序,并使用 pthread_kill()的线需要的时候醒来,但它是一种凌乱一个独立的信号处理程序。

The problem with this implementation is that the main thread is busy waiting for all worker threads to finish and worker threads are also constantly polling the jobs array to check for a new job. Is there a better way to do this when threads go to sleep and wake up when needed along the lines of a singal handler and using pthread_kill() but it is kind of messy with a separate signal handler.

推荐答案

您可以使用的条件变量使线程进入睡眠状态,直到信号。

You can use a conditional variable to make the threads go to sleep until signaled.

volatile int jobs[MAX_THREADS]; // global job indicator array
pthread_cond_t th_cond;     // threads wait on this
pthread_mutex_t th_mutex;   // mutex to protect the signal
int busyThreads = MAX_THREADS;

pthread_cond_t m_cond;      // main thread waits on this
pthread_mutex_t m_mutex;    // mutex to protect main signal

thread_execute(void *args)
{
  tid = get_id(args);
  while(jobs[tid] != -1)
  {
    if(jobs[tid] == 0) continue; // no job
    if(jobs[tid] == JOBS_1)
    {
      jobs1();
      jobs[tid] = 0; // go back to idle state
      pthread_mutex_lock(&th_mutex);      
          pthread_mutex_lock(&m_mutex);   
          --busyThreads;                       // one less worker
          pthread_cond_signal(&m_cond);        // signal main to check progress
          pthread_mutex_unlock(&m_mutex);
      pthread_cond_wait(&th_cond, &th_mutex);   // wait for next job
      pthread_mutex_unlock(&th_mutex);      
    }
    if(jobs[tid] == JOBS_2)
    {
      jobs2();
      jobs[tid] = 0; // go back to idle state
      pthread_mutex_lock(&th_mutex);
      --busyThreads;
      pthread_cond_wait(&th_cond, &th_mutex);
      pthread_mutex_unlock(&th_mutex);
    }
  }

  pthread_exit(NULL);
}

然后主:

int main()
{
  sem_init(&semaphore, 0, 0);
  jobs[0...MAX_THREADS] = 0;
  spawn_threads();

  // Dispatch first job
  jobs[0...MAX_THREADS] = JOBS_1;
  int semvalue = 0;

  pthread_mutex_lock(&m_mutex);
  while(busyThreads > 0)        // check number of active workers
      pthread_cond_wait(&m_cond, &m_mutex);   
  pthread_mutex_unlock(&m_mutex);

  busyThreads = MAX_THREADS;
  pthread_mutex_lock(&th_mutex);
  pthread_cond_broadcast(&th_cond);   // signal all workers to resume
  pthread_mutex_unlock(&th_mutex);

  // same for JOBS_2;

  jobs[0...MAX_THREADS] = -1; // No more jobs
  pthread_join();
}

这篇关于在pthread中醒来单个线程,而不是忙等待的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆