multithread launching order

前端 未结 4 1984
庸人自扰
庸人自扰 2021-01-15 10:00

I have 4 threads to create thread1, thread2, thread3 and thread4:

pthread_create(thread1,NULL,thread_func1,NULL);
pthread_create(thread2,NULL,thread_func2,NU         


        
4条回答
  •  礼貌的吻别
    2021-01-15 10:29

    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 
    #include 
    
    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.

提交回复
热议问题