multithread launching order

2020-03-29 18:57发布

I have 4 threads to create thread1, thread2, thread3 and 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);

looking in the debug , The order of launched threads is not the same as defined in the source code. Are there a solution to launch the threads with an order that I could define?

标签: c linux pthreads
4条回答
2楼-- · 2020-03-29 19:39

The launch order is sequential, in that the create calls happen in the order they're written.

However the scheduler for whatever reason isn't scheduling the newly launched threads in the order you hoped. If the order matters perhaps threads isn't what you want? The big advantage with threads is that they don't always get scheduled in a sequential order!

If you really want though you can use synchronisation primitives (e.g. a series of mutexes, or a condvar) to ensure that up to a certain point happens in predictable order, but from that point onwards the order will still be down to the whims of the scheduler. As an example this code guarantees that each thread will print its ID in the order they were created:

#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
  }
}

I've used while(1); to simulate some real work happening. It does this with a mutex protecting the "current" thread, i.e. the order of initialisation and then a condvar to make sleeping/waking possible. It broadcasts to all threads who then check to see which one is up next. You could design as system that skips the broadcast, but that complicates things for relatively little gain.

You can also add more synchronisation if required at other points, but the more you synchronise things the less point there is in having threads in the first place.

Ideally if things need to happen in a predictable order they should be done before spawning threads, not as soon as the threads spawn, e.g.:

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);

such that by the time the threads are created you don't care which one actually gets given the chance to run first.

查看更多
家丑人穷心不美
3楼-- · 2020-03-29 19:43

here after the solution I used

#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
  }
}
查看更多
Evening l夕情丶
4楼-- · 2020-03-29 19:52

I don't think you really care which thread executed first. If you just need an unique identifier for the four threads, check pthread_self. To have sequential IDs, call the ID allocator from within the thread; or generate the ID and pass it as user parameter when calling pthread_create.

查看更多
兄弟一词,经得起流年.
5楼-- · 2020-03-29 19:56
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()

This is VERY close to the other question posted recently and just as err.. 'strange'

查看更多
登录 后发表回答