多线程发射顺序

时间:2012-05-16 10:36:23

标签: c linux pthreads

我有4个线程来创建thread1,thread2,thread3和thread4:

pthread_create(thread1,NULL,thread_func1,NULL);
pthread_create(thread2,NULL,thread_func2,NULL);
pthread_create(thread3,NULL,thread_func3,NULL);
pthread_create(thread4,NULL,thread_func4,NULL);

查看调试,启动的线程的顺序与源代码中定义的顺序不同。 有没有一个解决方案来启动我可以定义的订单线程?

4 个答案:

答案 0 :(得分:4)

启动订单顺序的,因为创建调用按照它们编写的顺序发生。

但是,无论出于何种原因,的调度程序都不按照您希望的顺序调度新启动的线程。如果订单很重要或许线程不是你想要的?线程的最大优点是它们并不总是按顺序排列!

如果你真的想要,虽然你可以使用同步原语(例如一系列互斥,或condvar)来确保达到某个点以可预测的顺序发生,但从那一点开始,订单仍然会下降到调度程序的突发奇想。作为示例,此代码保证每个线程将按照创建的顺序打印其ID:

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

static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void sync_threads(const int num, int *cur) {
  pthread_mutex_lock(&mut);
  while (*cur != num) {
    pthread_cond_wait(&cond, &mut);
  }
  // Do work that must happen in order here:
  printf("Thread: %d\n", num);
  ++*cur;
  pthread_mutex_unlock(&mut);
  pthread_cond_broadcast(&cond);
}

static int num = 1;

void *thread1(void *d) {
  sync_threads(1,&num);
  while (1); // Rest of work happens whenever
  return NULL;
}

void *thread2(void *d) {
  sync_threads(2,&num);
  while (1);
  return NULL;
}

void *thread3(void *d) {
  sync_threads(3,&num);
  while (1);
  return NULL;
}

void *thread4(void *d) {
  sync_threads(4,&num);
  while (1);
  return NULL;
}

int main() {
  pthread_t t1,t2,t3,t4;
  pthread_create(&t1, NULL, thread1, NULL);
  pthread_create(&t2, NULL, thread2, NULL);
  pthread_create(&t3, NULL, thread3, NULL);
  pthread_create(&t4, NULL, thread4, NULL);
  while(1) {
    // some work
  }
}

我用while(1);来模拟一些真实的工作。它通过保护“当前”线程的互斥锁,即初始化顺序,然后使用condvar来进行睡眠/唤醒。它向所有线程广播,然后检查下一个线程。您可以设计为跳过广播的系统,但这会使事情变得复杂,而收益相对较少。

如果需要,您还可以在其他位置添加更多同步,但同步事物越多,首先拥有线程的点就越少。

理想情况下,如果事情需要以可预测的顺序发生,那么它们应该在生成线程之前完成,而不是在线程产生时,例如:

fixed_init_for_thread1();
fixed_init_for_thread2();
fixed_init_for_thread3();
fixed_init_for_thread4();

pthread_create(thread1,NULL,thread_func1,NULL);
pthread_create(thread2,NULL,thread_func2,NULL);
pthread_create(thread3,NULL,thread_func3,NULL);
pthread_create(thread4,NULL,thread_func4,NULL);

这样,在创建线程时,你并不关心哪一个实际上有机会先运行。

答案 1 :(得分:1)

我认为你真的不关心首先执行哪个线程。如果您只需要四个线程的唯一标识符,请检查pthread_self。要获得顺序ID,请从线程内调用ID分配器;或者在调用pthread_create时生成ID并将其作为用户参数传递。

答案 2 :(得分:1)

在我使用的解决方案之后

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

static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static bool wait = TRUE;

void thread_sync() {
  pthread_mutex_lock(&mut);
  wait = FALSE;
  pthread_cond_signal(&cond);
  pthread_mutex_unlock(&mut);
}
void thread_wait_sync() {
  pthread_mutex_lock(&mut);
  if (wait==TRUE)
  {
      pthread_cond_wait(&cond,&mut);
  }
  wait = TRUE;
  pthread_mutex_unlock(&mut);
}

void *thread1(void *d) {
  thread_sync();
  while (1); // Rest of work happens whenever
  return NULL;
}

void *thread2(void *d) {
  thread_sync();
  while (1);
  return NULL;
}

void *thread3(void *d) {
  thread_sync();
  while (1);
  return NULL;
}

void *thread4(void *d) {
  while (1);
  return NULL;
}

int main() {
  pthread_t t1,t2,t3,t4;
  pthread_create(&t1, NULL, thread1, NULL);
  thread_wait_sync();
  pthread_create(&t2, NULL, thread2, NULL);
  thread_wait_sync();
  pthread_create(&t3, NULL, thread3, NULL);
  thread_wait_sync();
  pthread_create(&t4, NULL, thread4, NULL);
  while(1) {
    // some work
  }
}

答案 3 :(得分:0)

Move 'pthread_create(thread2,NULL,thread_func2,NULL);' into thread_func1()
Move 'pthread_create(thread3,NULL,thread_func2,NULL);' into thread_func2()
Move 'pthread_create(thread4,NULL,thread_func2,NULL);' into thread_func3()

这非常接近最近发布的另一个问题,就像错误的......'奇怪'