如何加入任何首先完成的线程?

时间:2017-05-27 00:11:32

标签: multithreading pthreads pthread-join

主线程产生> 1个线程,每个线程都可以使用错误值调用return。如果发生这种情况,其他线程继续没有意义,因此应该取消它们。

所以,我想要我的主线程:

  • 首先加入任何线程;
  • 检查此线程是否返回错误,如果是,则取消所有其他线程。

但是,pthread_join要求我指定要加入的线程。如果我打电话,例如,pthread_join(thread1, thread1_ret)thread2完成错误,那么thread2完成之前,我将无法知道thread1已完成错误,并且thread2过早完成的事实很可能意味着thread1当前正在等待一个永远不会发出信号的条件变量,因为只有thread2可能会发出变量信号......所以,不好。< / p>

如果thread1完成,我希望我的主要帖子取消thread2,反之亦然。

如何做到这一点?

2 个答案:

答案 0 :(得分:1)

  

如何做到这一点?

您需要一个单独的沟通渠道。

典型的解决方案涉及队列(已完成的线程)和条件变量。

以错误结束的线程将自身置于队列中并在返回之前发出信号。主线程等待条件,检查队列,并加入它在那里找到的线程,然后取消所有其他线程。

另请注意,异步线程取消很难实现。通常最好有一个所有线程定期检查的全局变量:while (!exit_requested) { do_work(); }

答案 1 :(得分:0)

你想要这样的东西:

struct thread_data {
  int stop;
  pthread_cond_t * flag;
  pthread_mutex_t * lock;
  int * failCount;
  int * successCount;
};

void * foobar(void * ptr)
{
  struct thread_data * data = (struct thread_data*)ptr;
  int fail = 0;
  while (isWorkToBeDone() && !data->stop) {
    // do some work

    if (encounteredError()) {
      pthread_mutex_lock(data->lock);
      data->failCount += 1;
      fail = 1;
      pthread_cond_signal(data->flag);
      pthread_mutex_unlock(data->lock);
    }
  }

  // clean up
  if (!fail) {
    pthread_mutex_lock(data->lock);
    data->successCount += 1;
    pthread_cond_signal(data->flag);
    pthread_mutex_unlock(data->lock);
  }

  pthread_exit(NULL);
}


int runThreads()
{
  pthread_t * threads;

  pthread_mutex_t lock;
  pthread_cond_t flag;

  int i;
  struct thread_data data;

  threads = malloc(sizeof(*threads)*numThreads);
  if (!threads) {
    // handle malloc error
    return 0;
  }

  // initialize mutex and condition variable
  pthread_mutex_init(&lock, NULL);
  pthread_cond_init(&flag, NULL);

  data.stop = 0;
  data.flag = &flag;
  data.lock = &lock;
  data.failCount = 0;
  data.successCount = 0;

  for (i = 0; i < numThreads; ++i) {
    if (!pthread_create(threads+i, NULL, foobar,
        (void *)(threads+i))) {
      // handle thread creation error
    }
  }

  while (!data.stop) {
    pthread_mutex_lock(&lock);
    pthread_cond_wait(&cond, &lock);
    // a thread just finished
    if (data.failCount > 0) {
      data.stop = 1;
    } else if (data.successCount == numThreads) {
      data.stop = 1;
    }
    pthread_mutex_unlock(&lock);
  }

  for (i = 0; i < numThreads; ++i) {
    pthread_join(threads[i], NULL);
  }

  pthread_mutex_destroy(&lock);
  pthread_cond_destroy(&flag);
  free(threads);
}

它的工作方式是等待一个线程失败,或者所有线程都成功,然后让所有线程知道停止工作并通过stop变量干净地退出。

不是让线程检查stop变量,而是调用pthread_kill(),但要更好地退出每个线程。