Pthreads & Concurrency Acknowledgements The material in this tutorial is based in part on: POSIX Threads Programming , by Blaise Barney History Advantages Content History Different versions of threads each hardware vendor created own version IEEE POSIX 1003.1c Standard C programming types and procedure calls Advantages Potential program performance gains Platform fork() pthread_create() real user sys real user sys AMD 2.4 GHz Opteron 41.07 60.08 9.01 0.66 0.19 0.43 IBM 1.9 GHz POWER5 p5-575 64.24 30.78 27.68 1.75 0.69 1.10 IBM 1.5 GHz POWER4 104.05 48.64 47.21 2.01 1.00 1.52 INTEL 2.4 GHz Xeon 54.95 1.64 0.67 0.90 1.54 20.78 Advantages More efficient inter-thread communication Threaded applications Overlap CPU work and I/O Priority/Real-time scheduling Asynchronous event handling The Pthreads API Thread management Create, detach, join Set/query thread attributes Mutex Mutual Exclusion Condition variables Address communications between threads Non-mutex synchronization Read/write locks Barriers The Pthreads API Naming conventions Routine Prefix Functional Group pthread_ Thread themselves and miscellaneous subroutines pthread_attr_ Thread attributes objects pthread_mutex_ Mutexes pthread_mutexattr_ Mutex attributes objects pthread_cond_ Condition variables pthread_condattr_ Condition attributes objects pthread_key_ Thread-specific data keys Create & Terminate Program: Hello World Creation Routine pthread_create( thread, attr, start_routine, arg) Termination Four ways for a Pthread to terminate Returns from start_routine Call pthread_exit routine Cancel by another thread through pthread_cancel routine exit call Example: Hello World Program Requirements Print “Hello World” through standard output Use two threads to finish the task, one should print “Hello”, the other should print “World” Terminate all related threads related after finishing the printing task Example: Hello World #include <stdio.h> #include <pthread.h> …… Example: Hello World void print_message_function( void *ptr ) { char *message; message = (char *) ptr; printf("%s ", message); } Example: Hello World main() { pthread_t thread1, thread2; char *message1 = "Hello"; char *message2 = "World"; …… } Example: Hello World main() { pthread_t thread1, thread2; char *message1 = "Hello"; char *message2 = "World"; …… } Example: Hello World main() { pthread_t thread1, thread2; char *message1 = "Hello"; char *message2 = "World"; …… } Example: Hello World main() { …… pthread_create(&thread1, pthread_attr_default, (void*)&print_message_function, (void*) message1); pthread_create(&thread2, pthread_attr_default, (void*)&print_message_function, (void*) message2); exit(0); } Example: Hello World main() { …… pthread_create(&thread1, pthread_attr_default, (void*)&print_message_function, (void*) message1); pthread_create(&thread2, pthread_attr_default, (void*)&print_message_function, (void*) message2); exit(0); } Example: Hello World main() { …… pthread_create(&thread1, pthread_attr_default, (void*)&print_message_function, (void*) message1); pthread_create(&thread2, pthread_attr_default, (void*)&print_message_function, (void*) message2); exit(0); } Example: Hello World main() { …… pthread_create(&thread1, pthread_attr_default, (void*)&print_message_function, (void*) message1); pthread_create(&thread2, pthread_attr_default, (void*)&print_message_function, (void*) message2); exit(0); } Example: Hello World main() { …… pthread_create(&thread1, pthread_attr_default, (void*)&print_message_function, (void*) message1); pthread_create(&thread2, pthread_attr_default, (void*)&print_message_function, (void*) message2); exit(0); } Example: Hello World main() { …… pthread_create(&thread1, pthread_attr_default, (void*)&print_message_function, (void*) message1); pthread_create(&thread2, pthread_attr_default, (void*)&print_message_function, (void*) message2); exit(0); } Example: Hello World main() { …… pthread_create(&thread1, pthread_attr_default, (void*)&print_message_function, (void*) message1); pthread_create(&thread2, pthread_attr_default, (void*)&print_message_function, (void*) message2); exit(0); } Example: Hello World Thread 1 default thread Thread 2 Example: Hello World Thread 1 default thread Thread 2 Example: Hello World Thread 1 default thread Thread 2 Example: Hello World Thread 1 default thread Thread 2 Example: Hello World Thread 1 default thread Thread 2 Example: Hello World Thread 1 Printf default thread Thread 2 Printf Example: Hello World Thread 1 Printf default thread Exit Thread 2 Printf Example: Hello World Thread 1 standard output Thread 2 Thread 1 default thread Thread 2 Return Example: Hello World void print_message_function( void *ptr ) { char *message; message = (char *) ptr; printf("%s ", message); } main() { …… pthread_exit(); //exit(0); } Example: Hello World void print_message_function( void *ptr ) { char *message; message = (char *) ptr; printf("%s ", message); pthread_exit(); } main() { …… pthread_exit(); //exit(0); } Passing parameters to threads The pthread_create() routine permits the programmer to pass one argument to the thread start routine. For cases where multiple arguments must be passed, this limitation is overcome by creating a structure which contains all of the arguments, and then passing a pointer to that structure. All arguments must be passed by reference and cast to (void *). Joining and detaching threads pthread_join (threadid,status) blocks the calling thread until the specified threadid thread terminates. target thread's termination return status placed in status if specified in the target thread's call to pthread_exit(). A joining thread can match one pthread_join() call. It is a logical error to attempt multiple joins on the same thread. pthread_detach (threadid, status) to explicitly detach a thread pthread_attr_setdetachstate (attr,detachstate) pthread_attr_getdetachstate (attr, detachstate) Create & Destroy Lock & Unlock Program: Bounded Buffer Mutex Mutual Exclusion Act as a “lock” to prevent race conditions Typical sequence of use create, initialize lock, unlock destroy Losers in the competition for the mutex variable have to block Creating & Destroying Type: pthread_mutex_t Initializing Statically ○ pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER Dynamically ○ pthread_mutex_init (mutex, attr) pthread_mutex_attr_t attr specifies protocol for priorities, priority ceiling, and process sharing Destroying pthread_mutex_destroy – to delete a mutex object pthread_mutex_attr_destroy – to delete a mutex attr object Lock & Unlock Lock pthread_mutex_lock (mutex) ○ blocks calling thread if mutex already locked pthread_mutex_trylock(mutex) ○ returns with “busy” code if already locked Unlock pthread_mutex_unlock (mutex) Error ○ mutex is released ○ mutex owned by others