Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The launch order <em>is</em> sequential, in that the create calls happen in the order they're written. </p> <p>However the scheduler for whatever reason <em>isn't</em> 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!</p> <p>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:</p> <pre><code>#include &lt;pthread.h&gt; #include &lt;stdio.h&gt; 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(&amp;mut); while (*cur != num) { pthread_cond_wait(&amp;cond, &amp;mut); } // Do work that must happen in order here: printf("Thread: %d\n", num); ++*cur; pthread_mutex_unlock(&amp;mut); pthread_cond_broadcast(&amp;cond); } static int num = 1; void *thread1(void *d) { sync_threads(1,&amp;num); while (1); // Rest of work happens whenever return NULL; } void *thread2(void *d) { sync_threads(2,&amp;num); while (1); return NULL; } void *thread3(void *d) { sync_threads(3,&amp;num); while (1); return NULL; } void *thread4(void *d) { sync_threads(4,&amp;num); while (1); return NULL; } int main() { pthread_t t1,t2,t3,t4; pthread_create(&amp;t1, NULL, thread1, NULL); pthread_create(&amp;t2, NULL, thread2, NULL); pthread_create(&amp;t3, NULL, thread3, NULL); pthread_create(&amp;t4, NULL, thread4, NULL); while(1) { // some work } } </code></pre> <p>I've used <code>while(1);</code> 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.</p> <p>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.</p> <p>Ideally if things need to happen in a predictable order they should be done <em>before</em> spawning threads, not as soon as the threads spawn, e.g.:</p> <pre><code>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); </code></pre> <p>such that by the time the threads are created you don't care which one actually gets given the chance to run first.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload