POSIX Threads and Joins – Parallel Programming – PART 1

During a long time we were “blessed” with computers that had only single CPU. The single CPU usually had a mediocre single core and thread. All software developed on that time executed sequential processing.

However, multi-cores and multi-threads processors were introduced in the market but if you do not develop your software trying to explore the hardware advantages your software might have the same performance if running in a single cpu machine.

You need to think also if you software will run in a computer isolated or if your software will be able to run in multiple computers sharing a common network and organize different tasks to resolve a common problem.

Today, I will write this post for my own reference using the POSIX threads and how to have the best usage of joins and mutex implementation. I am running in a ubuntu 10.04 but if you are running Windows you can use these examples installing the POSIX win32 compatibility module or installing Cygwin to simulate a linux shell.

Code compilation

All codes on this post were compiled using gcc and invoking the POSIX libraries thru command like under ubuntu 10.04. For example you can use:

gcc -pthread <my source code.c>

Threads

The first code is related to a model where we do not share the same memory space and there is no policy regarding the thread priorities or resources access management (although the threads runs in the same process sharing the same memory space this first example to resource are conflicted).

It is a simple code that creates 3 threads, passes arguments to them using strings and integers and then they are terminated.

Take a look in the code below:

</pre>
void *print_message_function( void *ptr );
void *print_integer_function( void * i );
main()
{
 pthread_t thread1, thread2, thread3;
 char *s_parameter_t1 = "thread 1 - passing a string!";
 char *s_parameter_t2 = "thread 2 - passing a string!";
 int i_parameter_t3 = 1973; /* my birthday */
 int i_result_t1, i_result_t2, i_result_t3;

/* Creating two threads.. one using a funtion to process a string and another one to a integer
 - Note for multiple data you can use a data structure as parameter making a cast to void *
 - the data passed is shared in memory space for ALL threads of same process, so passing pointer
 addresses could be dangeours in concurrence state */
 i_result_t1 = pthread_create( &thread1, NULL, print_message_function, (void*) s_parameter_t1);
 i_result_t2 = pthread_create( &thread2, NULL, print_message_function, (void*) s_parameter_t2);
 i_result_t3 = pthread_create( &thread3, NULL, print_integer_function, (void*) &i_parameter_t3);

printf("execute me several times.. you will see no order and possile concurrences !!!\n");

/* checking if there is some thread fail */
 if (i_result_t1 == i_result_t2 == i_result_t3 != 0)
 {
 printf("Thread 1 returns: %d\n",i_result_t1);
 printf("Thread 2 returns: %d\n",i_result_t2);
 printf("Thread 3 returns: %d\n",i_result_t3);
 }

/* termination of threads.. we could kill all thread using exit(0) to aborting the process*/
 pthread_exit(&thread1);
 pthread_exit(&thread2);
 pthread_exit(&thread3);
}

void *print_message_function( void *ptr )
{
 char *message;
 message = (char *) ptr;
 printf("%s \n", message);
}

void *print_integer_function(void * i)
{
 int i_value = *((int *)i);
 printf("value integer %d\n",i_value);
}
<pre>

Basically we are creating three threads using pthread_create(), where 2 received a string parameter and one a integer parameter. Then the threads are terminated using pthread_exit(), thus the “thread pointers” are free at this time.

Compile and run the code several times.. you will see something like this in your shell:

bytesthink@ubuntu:~/code/code$ gcc -pthread pthreads.c
bytesthink@ubuntu:~/code/code$ ./a.out
execute me several times.. you will see no order and possile concurrences !!!
thread 2 – passing a string!
thread 1 – passing a string!
value integer 1973
bytesthink@ubuntu:~/code/code$ ./a.out
thread 1 – passing a string!
execute me several times.. you will see no order and possile concurrences !!!
value integer 1973
thread 2 – passing a string!
bytesthink@ubuntu:~/code/code$ ./a.out
thread 1 – passing a string!
thread 2 – passing a string!
execute me several times.. you will see no order and possile concurrences !!!
value integer 1973


Note there is no policy used to execute the entry points functions. You can see the code is not sequential because the threads 1, 2 and 3 are executed and no order is respected. The machine executes the first thread available in parallel manner.

Synchronizing threads with JOIN

The previous example is a good model when we have threads solving different problems (tasks) and there is no independence among them because the “main” does not care about the order of results processed by each one. Let’s change the code a little bit in order to allow us to synchronize the threads in the “main” code. For this, let’s use pthread_join() function:

</pre>
void *print_message_function( void *ptr );
void *print_integer_function( void * i );
main()
{
 pthread_t thread1, thread2, thread3;
 char *s_parameter_t1 = "thread 1 - passing a string!";
 char *s_parameter_t2 = "thread 2 - passing a string!";
 int i_parameter_t3 = 1973; /* my birthday */
 int i_result_t1, i_result_t2, i_result_t3;

/* Creating two threads.. one using a funtion to process a string and another one to a integer
 - Note for multiple data you can use a data structure as parameter making a cast to void *
 - the data passed is shared in memory space for ALL threads of same process, so passing pointer
 addresses could be dangeours in concurrence state */
 i_result_t1 = pthread_create( &thread1, NULL, print_message_function, (void*) s_parameter_t1);
 pthread_join(thread1, NULL);
 i_result_t2 = pthread_create( &thread2, NULL, print_message_function, (void*) s_parameter_t2);
 pthread_join(thread2, NULL);
 i_result_t3 = pthread_create( &thread3, NULL, print_integer_function, (void*) &i_parameter_t3);
 pthread_join(thread3, NULL);

printf("execute me several times.. you will see no order and possile concurrences !!!\n");

/* checking if there is some thread fail */
 if (i_result_t1 == i_result_t2 == i_result_t3 != 0)
 {
 printf("Thread 1 returns: %d\n",i_result_t1);
 printf("Thread 2 returns: %d\n",i_result_t2);
 printf("Thread 3 returns: %d\n",i_result_t3);
 }

/* termination of threads.. we could kill all thread using exit(0) to aborting the process*/
 pthread_exit(&thread1);
 pthread_exit(&thread2);
 pthread_exit(&thread3);
}

void *print_message_function( void *ptr )
{
 char *message;
 message = (char *) ptr;
 printf("%s \n", message);
}

void *print_integer_function(void * i)
{
 int i_value = *((int *)i);
 printf("value integer %d\n",i_value);
}
<pre>

Now execute the code several times again. You will see:

bytesthink@ubuntu:~/code/code$ gcc -pthread pthreads_join.c
bytesthink@ubuntu:~/code/code$ ./a.out
thread 1 – passing a string!
thread 2 – passing a string!
value integer 1973
execute me several times.. you will see no order and possile concurrences !!!
bytesthink@ubuntu:~/code/code$ ./a.out
thread 1 – passing a string!
thread 2 – passing a string!
value integer 1973
execute me several times.. you will see no order and possile concurrences !!!
bytesthink@ubuntu:~/code/code$ ./a.out
thread 1 – passing a string!
thread 2 – passing a string!
value integer 1973
execute me several times.. you will see no order and possile concurrences !!!
bytesthink@ubuntu:~/code/code$ ./a.out
thread 1 – passing a string!
thread 2 – passing a string!
value integer 1973
execute me several times.. you will see no order and possile concurrences !!!
bytesthink@ubuntu:~/code/code$ ./a.out
thread 1 – passing a string!
thread 2 – passing a string!
value integer 1973

As you see, the “join” has a function of blocking. It means, the pthread_join() making usage of the thread_id identified by the thread pointer, is saying to “main” execution, wait to finish this execution. So, even if thread 2 or 3 finish first, the main will remain blocked waiting the thread 1 finish its work because there is a “join” defined. So, on this way you can guarantee the sequence of final results but you still have the threads working in parallel.

Source Code

You can download the first code here!

What’s coming in next part ?

In the next part let’s take a look in mutexes and conditional mutexes. Let’s talk also how useful is volatile datatype in C/C++ for multi-core processors. No time to write more on this wonderful Sunday! Mexican food is waiting for me!!! 🙂

16 thoughts on “POSIX Threads and Joins – Parallel Programming – PART 1

  1. Interesting article introduction article but could you adapt your layout/css/code so that one could read your code without horizontal scrolling? The code block is only ~30 char wide on my screen.

  2. Pingback: jordan cp3.xi orange uk trainers

  3. Pingback: cat carter maize

  4. Pingback: bleu jaune rouge big boys lebron soldier 11

  5. Pingback: air force 1 low balsam green uk trainers

  6. Pingback: uk trainers preschool nike free run 2 boy flesh

  7. Pingback: marron kaki rouge supreme justin bieber t shirt

  8. Pingback: hvid lyser酶d nike zvezdochka

  9. Pingback: sort r酶d nike dunk sky hi essential

  10. Pingback: 胁芯谢褜褌 锌褍褉锌褍褉薪褘泄 adidas 2012 superstar animals

  11. Pingback: cheetah print jordan 1

  12. Pingback: adidas stan smith 10

  13. Pingback: adidas arkyn cloud white cloud white ash pearl cq2748

  14. Pingback: 銉娿偆銈?nike aptare 銉戙兗銉椼儷 銈儸銉炽偢

  15. Pingback: wei脽 schwarz damen nike air max 2013

Leave a Reply