POSIX Threads Nezer J. Zaidenberg. References Advanced programming for the UNIX environment (2nd...

29
POSIX Threads Nezer J. Zaidenberg

Transcript of POSIX Threads Nezer J. Zaidenberg. References Advanced programming for the UNIX environment (2nd...

Page 1: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

POSIX Threads

Nezer J. Zaidenberg

Page 2: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

ReferencesAdvanced programming for the UNIX

environment (2nd edition chapter 11+12 This material does not exist in first edition)

Many manuals exist on the webYolinux.com : POSIX thread (pthread) libraries

(very basic and I found some mistakes there!)http://www.ibm.com/developerworks/library/l-p

osix1.html (and chapters 2/3)

Programming with POSIX(R) Threads by David Botenhof (more advanced then this course)

Page 3: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Simple thread program code

Page 4: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

#include <stdio.h>#include <stdlib.h>#include <pthread.h>

void *print_message_function( void *ptr );

main(){ pthread_t thread1, thread2; char *message1 = "Thread 1"; char *message2 = "Thread 2"; pthread_create( &thread1, NULL, print_message_function, (void*)

message1); pthread_create( &thread2, NULL, print_message_function, (void*)

message2); pthread_join( thread1, NULL); pthread_join( thread2, NULL); exit(0);}

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

Page 5: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Two important notes

To compile :C : gcc -lpthread thread.cC++ : g++ -lpthread thread.cxxOther platforms and compilers

may require -pthread flag insteadNever code like this

You should check pthread create return value

Page 6: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Why do we need thread libraryIn Linux malloc(3) is normally not

thread safe to speed things up (no locking and unlocking)

That means that when we use threads – we must use different malloc(3)

This is also true in Windows while in OSX malloc is always thread safe.

Page 7: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Pthread_create(3)SYNOPSIS #include <pthread.h>

int pthread_create(pthread_t * thread, const pthread_attr_t * attr, void * (*start_routine)(void *), void *arg);Argumentsthread - returns the thread id. (unsigned long int defined in

bits/pthreadtypes.h)attr - Set to NULL if default thread attributes are used. (else

define members of the struct pthread_attr_t defined in bits/pthreadtypes.h)

void * (*start_routine) - pointer to the function to be threaded. Function has a single argument: pointer to void.

*arg - pointer to argument of function. To pass multiple arguments, send a pointer to a structure.

Page 8: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Pthread exit(3) – exit(2) for threadsSYNOPSIS #include <pthread.h>

void pthread_exit(void *retval);

Arguments:

* retval - Return value of thread.

Page 9: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Pthread join(3) – wait(2) for threadsSYNOPSIS #include <pthread.h>

int pthread_join(pthread_t thread, void **value_ptr);

ArgumentsValue_ptr = the value returned by thread

This function is BLOCKING!!!

Page 10: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Passing arguments to/from threadsCan be done using the void

pointer (cast the void * into a struct and point into any number of arguments)

Return values can be returned in the same way

Shared memory is also used for this (but is less recommended because of problems with syncing)

Page 11: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Example (1/3)#define _MULTI_THREADED#include <pthread.h>#include <stdio.h>#include "check.h”typedef struct{

int value; char string[128];} thread_parm_t;void *threadfunc(void *parm){ thread_parm_t *p = (thread_parm_t *)parm; printf("%s, parm = %d\n", p->string, p->value); free(p); return NULL;}

Page 12: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Example 2/3int main(int argc, char **argv){

pthread_t thread; int rc=0; thread_parm_t *parm=NULL;

printf("Create a thread attributes object\n");parm = malloc(sizeof(thread_parm_t));

parm->value = 5; strcpy(parm->string, "Inside first thread"); rc = pthread_create(&thread, NULL, threadfunc,

(void *)parm); parm = malloc(sizeof(thread_parm_t));

parm->value = 77; strcpy(parm->string, "Inside second thread");

Page 13: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Example 3/3

rc = pthread_create(&thread, NULL, threadfunc, (void *)parm);

sleep(5);

printf("Main completed\n");

return 0;

}

Page 14: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Problems with example

Check return code (existed in the original example)

Don’t use sleep() to wait for thread! – use pthread_join(3).

Avoid heap memory allocation. (It was used in the original example and I wanted to show shared memory and cases where one thread malloc(3)s and another free(3).)

Page 15: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Thread attributes detached state (joinable? Default:

PTHREAD_CREATE_JOINABLE. Other option: PTHREAD_CREATE_DETACHED)

scheduling policy (real-time? PTHREAD_INHERIT_SCHED,PTHREAD_EXPLICIT_SCHED,SCHED_OTHER)

scheduling parameter inheritsched attribute (Default: PTHREAD_EXPLICIT_SCHED

Inherit from parent thread: PTHREAD_INHERIT_SCHED) scope (Kernel threads: PTHREAD_SCOPE_SYSTEM User

threads: PTHREAD_SCOPE_PROCESS Pick one or the other not both.)

guard size stack address (See unistd.h and bits/posix_opt.h

_POSIX_THREAD_ATTR_STACKADDR) stack size (default minimum PTHREAD_STACK_SIZE set in

pthread.h),

Page 16: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

In the scope of this course we will always use NULL for thread attributes

Page 17: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Sync using mutex (1/2)#include <stdio.h>#include <stdlib.h>#include <pthread.h>

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;int counter = 0;

void *functionC(){ pthread_mutex_lock( &mutex1 ); counter++; printf("Counter value: %d\n",counter); pthread_mutex_unlock( &mutex1 );}

Page 18: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Syncing 2/2int main(){ int rc1, rc2; pthread_t thread1, thread2; if( (rc1=pthread_create( &thread1, NULL, &functionC, NULL)) ) { printf("Thread creation failed: %d\n", rc1); } if( (rc2=pthread_create( &thread2, NULL, &functionC, NULL)) )

{ printf("Thread creation failed: %d\n", rc2); }// ++counter pthread_join( thread1, NULL); pthread_join( thread2, NULL); exit(0);}

Page 19: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Pthread_mutex_lock

SYNOPSIS #include <pthread.h>

int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t

*mutex); int pthread_mutex_unlock(pthread_mutex_t

*mutex);

Lock function is blockingTry lock function is not blocking (it would lock if it can) Unlock release

Page 20: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Using cond (1/7)

#include <pthread.h>#include <stdio.h>#include <stdlib.h>

#define NUM_THREADS 3#define TCOUNT 10#define COUNT_LIMIT 12

int count = 0;int thread_ids[3] = {0,1,2};pthread_mutex_t count_mutex;pthread_cond_t count_threshold_cv;

Page 21: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Using cond 2/7

int main(int argc, char *argv[]){ int i, rc; pthread_t threads[3];

/* Initialize mutex and condition variable objects */ pthread_mutex_init(&count_mutex, NULL); pthread_cond_init (&count_threshold_cv, NULL); pthread_create(&threads[0], NULL, inc_count, (void

*)&thread_ids[0]); pthread_create(&threads[1], NULL, inc_count, (void

*)&thread_ids[1]); pthread_create(&threads[2], NULL, watch_count, (void

*)&thread_ids[2]);

Page 22: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Cond 3/7/* Wait for all threads to complete */ for (i = 0; i < NUM_THREADS; i++) { pthread_join(threads[i], NULL); } printf ("Main(): Waited on %d threads. Done.\n",

NUM_THREADS); /* Clean up and exit */pthread_mutex_destroy(&count_mutex); pthread_cond_destroy(&count_threshold_cv); pthread_exit (NULL);}

Page 23: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Using cond 4/7

void *inc_count(void *idp) { int j,i; double result=0.0; int *my_id = idp; for (i=0; i < TCOUNT; i++) { pthread_mutex_lock(&count_mutex); count++;

/* Check the value of count and signal waiting thread

when condition is reached. Note that this occurs while mutex is locked. */

Page 24: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Cond 5/7 if (count == COUNT_LIMIT) { pthread_cond_signal(&count_threshold_cv); printf("inc_count(): thread %d, count = %d Threshold

reached.\n", *my_id, count); } printf("inc_count(): thread %d, count = %d, unlocking

mutex\n”, *my_id, count); pthread_mutex_unlock(&count_mutex);

/* Do some work so threads can alternate on mutex lock */ for (j=0; j < 10000; j++) result = result + (double)random(); } pthread_exit(NULL);}

Page 25: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Using cond 6/7

void *watch_count(void *idp) { int *my_id = idp;

printf("Starting watch_count(): thread %d\n", *my_id);

/* Lock mutex and wait for signal. Note that the pthread_cond_wait

routine will automatically and atomically unlock mutex while it waits. Also, note that if COUNT_LIMIT is reached before this routine is

run by the waiting thread, the loop will be skipped to prevent

pthread_cond_wait from never returning. */

Page 26: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Using Cond 7/7

pthread_mutex_lock(&count_mutex); if (count < COUNT_LIMIT) { pthread_cond_wait(&count_threshold_cv,

&count_mutex); printf("watch_count(): thread %d Condition

signal received.\n", *my_id); } pthread_mutex_unlock(&count_mutex); pthread_exit(NULL);}

Page 27: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Things to note

Cond modify a mutex.Cond operations are

protected by mutex.

Page 28: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Good and bad things

Check return codeIn your practice code add

some work so threads will alternate

Page 29: POSIX Threads Nezer J. Zaidenberg. References  Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist.

Mutex and cond summary

Mutex Cond

standalone Requires mutex

When locking – I lock other threads

When locking – I lock myself

When unlocking – I allow other threads to access the critical section

Another thread allows me to access the critical section

Advisory locking – only lock threads that participate in the game

Advisory locking – only lock threads that participate in the game

Typically used by peers Typically used by consumer thread