Basic Multi-threaded Program on QNX Neutrino

Creating new threads in a Neutrino program is very easy. Just include pthread.h and use the pthread_*() functions.

Below is a simple program that creates two threads (in addition to the main() thread). The threads are created with the pthread_create() call.

One thread (‘funcThreadA’) prints out twenty ‘A’s, once every second, whilst the other thread (‘funcThreadB’) prints out ten ‘B’s, once every two seconds. Each letter appears on its own line.

The code to be performed by each thread is placed in its own function. A pointer to this function is then passed as an argument to the pthread_create() function. Once the function has been called, the thread starts immediately.

The pthread_join() function is used (twice, once for each thread) to tell the main() thread to wait for the thread mentioned in the call's argument, before continuing with execution. If main() did not wait for the threads, and it terminated before the extra threads had terminated, the extra threads would be terminated immediately. Using the ‘join’ ensures that the extra threads are run to completion before main() (and the extra threads) is terminated.

The order of calling the joins does not really matter -- if the join for the first thread is called before that for the second thread, but the second thread actually finishes first, no harm is done. All that happens is that the first join continues to wait until its thread has finished (ignoring what happens with the other thread) before resuming with main(), and then the second join resumes main() immediately since its thread has already terminated, so it doesn't have to wait.

Caution: When working with multi-threaded applications, accessing the same data with more than one thread or process gives rise to concurrency problems (mutual exclusion, critical sections, etc), which can be disastrous. Thus, it is necessary to familiarise onself thoroughly with the theory and practice surrounding this issue -- check out terms like “mutex”, “sempahore”, and so forth. Make sure you know what you are doing, and have taken the necessary precautions in your code.

For simplicity's sake, I do not share any data in this example, so that I can avoid complicating this code with concurrency handling code.


#include <pthread.h>
//--------------------------------------------------------------------
void *
funcThreadA( void )
{
   int a_loop;
   
   for ( a_loop = 1; a_loop <= 20; a_loop++ )
   {
      printf( "A\n" );
      sleep( 1 );
   }
   return;
}

//--------------------------------------------------------------------
void *
funcThreadB( void )
{
   int b_loop;
   
   for ( b_loop = 1; b_loop <= 10; b_loop++ )
   {
      printf( "B\n" );
      sleep( 2 );
   }
   return;
}

//--------------------------------------------------------------------
int
main( void )
{
   pthread_t threadA;
   pthread_t threadB;

   printf( "Main program starting\n" );
   /* create a new thread, additional to the existing one,
    * which is running this main program */
   pthread_create( &threadA, NULL, &funcThreadA, NULL );
   pthread_create( &threadB, NULL, &funcThreadB, NULL );
   printf( "Main program waiting\n" );
   pthread_join( threadA, NULL );
   pthread_join( threadB, NULL );
   printf( "Main program ending\n" );
   return 0;
}


Home About Me
Copyright © Neil Carter

Content last updated: 2003-10-31