Presentation is loading. Please wait.

Presentation is loading. Please wait.

Page 1 threads CS 360, WSU Vancouver POSIX Threads 1. Background 2. Threads vs. Processes 3. Thread Synchronization 4. Mutex Variables 5. Condition Variables.

Similar presentations


Presentation on theme: "Page 1 threads CS 360, WSU Vancouver POSIX Threads 1. Background 2. Threads vs. Processes 3. Thread Synchronization 4. Mutex Variables 5. Condition Variables."— Presentation transcript:

1 Page 1 threads CS 360, WSU Vancouver POSIX Threads 1. Background 2. Threads vs. Processes 3. Thread Synchronization 4. Mutex Variables 5. Condition Variables 6. Threads and UNIX

2 Page 2 threads CS 360, WSU Vancouver 1. Background l Threads are light-weight processes –only local variables in a function are specific to a thread (e.g. each thread has its own stack) –most other data is shared between threads (e.g. global variables & the heap) l pthreads is the POSIX threads standard. –The associated library interface is obtained by: –#include

3 Page 3 threads CS 360, WSU Vancouver 1.1. Reasons for Using Threads l Efficiency l Ease of data sharing l Common uses of parallelism: –overlapping I/O l do long I/O and CPU tasks at the same time –asynchronous events l wait for a response and do something else –real-time scheduling l quickly respond to important tasks –to utilize multiple processors

4 Page 4 threads CS 360, WSU Vancouver 2. Threads vs Processes l A thread uses less system resources than a similar process (for the same task). l A thread may require more user space resources than a similar process –depends on the implementation l Threads (within the same process) share everything except their stack and processor state continued

5 Page 5 threads CS 360, WSU Vancouver l The threads mechanism can be used instead of many different process-based mechanisms: –non-blocking I/O, shared memory (IPC), jmp() functions, signals,... l Threads use an inherently simpler shared memory mechanism than processes: –inter-thread communication is far easier –but it is also much easier to code parallelism errors (e.g. race conditions)

6 Page 6 threads CS 360, WSU Vancouver Problems with Threads l Unpredictable functioning (non-determinism) l Difficult to debug l Impossible to prove correct l Almost impossible to test thoroughly l Specific behavior not easily reproducible l Simple conceptually, but added complexities for dealing with many pitfalls

7 Page 7 threads CS 360, WSU Vancouver 2.1. Processes Example shared memory child 1: do_one_thing() child 2: do_another_thing() r1p r2p Global variables, etc shmid, shm_ptr, r1p, r2p Global variables, etc shmid, shm_ptr, r1p, r2p

8 Page 8 threads CS 360, WSU Vancouver #include #include #include #include #include #include #include void do_one_thing(int *pnum); void do_another_thing(int *pnum); int shmid, *shm_ptr;/* global, but not shared */ int *r1p, *r2p; : : 2.1. ints_processes.c continued

9 Page 9 threads CS 360, WSU Vancouver int main() { pid_t child1, child2; /* initialize shared memory */ shmid = shmget(IPC_PRIVATE, 2*sizeof(int), (IPC_CREAT | 0666)); if ((shm_ptr = (int *)shmat(shmid, (char *)0, 0)) < 0 ) perror("shmat failed"); : continued

10 Page 10 threads CS 360, WSU Vancouver /* initialise shared memory ints */ r1p = shm_ptr; r2p = (shm_ptr + 1); *r1p = 0; *r2p = 0; /* start forking children */ if ((child1 = fork()) == 0) { /* first child */ do_one_thing(r1p); exit(0); } : continued

11 Page 11 threads CS 360, WSU Vancouver if ((child2 = fork()) == 0) { /* second child */ do_another_thing(r2p); exit(0); } /* parent waits for children */ wait(NULL); wait(NULL); printf(“Final Values: %d, %d\n”, *r1p, *r2p); return 0; } continued

12 Page 12 threads CS 360, WSU Vancouver void do_one_thing(int *pnum) /* Waste time, and increment pnum */ { int i, j, x=0; for (i = 0; i < 4; i++) { printf("doing one thing\n"); for (j = 0; j < 10000; j++) x = x + i; (*pnum)++; } } continued

13 Page 13 threads CS 360, WSU Vancouver void do_another_thing(int *pnum) /* Waste time, and increment pnum. The code is almost the same as do_one_thing() */ { int i, j, x=0; for (i = 0; i < 4; i++) { printf("doing another \n"); for (j = 0; j < 10000; j++) x = x + i; (*pnum)++; } } continued

14 Page 14 threads CS 360, WSU VancouverUsage $ ints_processes doing one thing doing one thing doing another doing another doing another doing another doing one thing doing one thing Final Values: 4, 4 $ Order may vary each time ints_processes is executed.

15 Page 15 threads CS 360, WSU Vancouver 2.2. Threads Version thread 1: do_one_thing() thread 2: do_another_thing() Global variables, etc r1 r2 shared by default

16 Page 16 threads CS 360, WSU Vancouver 2.2. ints_threads.c #include /* Same functions as in simple_processes.c */ void do_one_thing(int *pnum); void do_another_thing(int *pnum); /* Global (and shared) integers */ int r1 = 0, r2 = 0; : continued

17 Page 17 threads CS 360, WSU Vancouver int main() { pthread_t thread1, thread2; pthread_create(&thread1, NULL, (void *) do_one_thing, (void *) &r1); pthread_create(&thread2, NULL, (void *) do_another_thing, (void *) &r2); pthread_join(thread1, NULL); pthread_join(thread2, NULL); printf(“Final Values: %d, %d\n”,r1, r2); return 0; }

18 Page 18 threads CS 360, WSU VancouverNotes l No need for shared memory library functions –threads approach has better performance –And simpler code l Difficult to program –synchronization problems (with processes, too) l Global variables are accessible to all threads –easy to make coding mistakes

19 Page 19 threads CS 360, WSU Vancouver 2.3. Thread Functions int pthread_create(pthread_t *thread, const pthread_attr_t attr, void *(*func)(void *), void *arg); Create a new thread with attributes specified in attr (usually NULL ). Start executing func() and pass it arg. l Consider carefully what to pass as the argument l Return 0 if ok, non-zero if error. continued

20 Page 20 threads CS 360, WSU Vancouver int pthread_join(pthread_t thread, void **value_ptr); Make the calling thread wait for the specified thread to terminate. value_ptr is assigned its return value (or PTHREAD_CANCELLED ).

21 Page 21 threads CS 360, WSU Vancouver 2.4. Matrix Multiplication Example l Parallelize matrix multiplication: 9 8 7 6 6 5 4 3 3 2 1 0 0 -1 -2 -3 * 1 2 3 4 4 5 6 7 7 8 9 10 10 11 12 13 = 150 180 210 240 84 102 120 138 18 24 30 36 -48 -54 -60 -66

22 Page 22 threads CS 360, WSU Vancouver Coding Approach Create MATSIZE (e.g. 4) threads: one for each column of the results[] array –each column will be calculated in parallel The parallelism could be increased by creating MATSIZE*MATSIZE threads: one for each element of the results[] array.

23 Page 23 threads CS 360, WSU Vancouvermatmult.c #include #include #define MATSIZE 4 void *matMult(void *); /* note the template */ void printMult(void); /* global and shared data */ int mat1[MATSIZE][MATSIZE] = {{9,8,7,6},{6,5,4,3},{3,2,1,0},{0,-1,-2,-3}}; int mat2[MATSIZE][MATSIZE] = {{1,2,3,4},{4,5,6,7},{7,8,9,10},{10,11,12,13}}; int result[MATSIZE][MATSIZE]; :

24 Page 24 threads CS 360, WSU Vancouver int main() { pthread_t thr[MATSIZE]; int i, *iPtr; for(i=0; i<MATSIZE; i++) iPtr = (int*) malloc(sizeof(int)); *iPtr = i; pthread_create(&thr[i], NULL, matMult, (void *)iPtr); for(i=0; i < MATSIZE; i++) pthread_join(thr[i], NULL); printMult(); return 0; }

25 Page 25 threads CS 360, WSU Vancouver void *matMult(void *colvPtr) { int i, j; int col = *colvPtr; free(colPtr); for(i=0; i < MATSIZE; i++) { result[i][col] = 0; for(j=0; j < MATSIZE; j++) result[i][col] += mat1[i][j] * mat2[j][col]; } return NULL; }

26 Page 26 threads CS 360, WSU Vancouver void printMult(void) { int i, j; for(i=0; i < MATSIZE; i++) { printf(“|”); for(j=0; j < MATSIZE; j++) printf(“%3d”, mat1[i][j]); printf(“|%c|”, (i==MATSIZE/2 ? ‘*’ : ‘‘)); for(j=0; j < MATSIZE; j++) printf(“%3d”, mat2[i][j]); printf(“|%c|”, (i==MATSIZE/2 ? ‘=’ : ‘‘)); for(j=0; j < MATSIZE; j++) printf(“%4d”, result[i][j]); printf(“|\n”); } }

27 Page 27 threads CS 360, WSU Vancouver 3. Thread Synchronization pthread_join() –like wait() for processes l mutex variables –like binary semaphores for processes l condition variables –wait for an ‘event’ (e.g. a variable is assigned a certain value), which is ‘signaled’ by another thread.

28 Page 28 threads CS 360, WSU Vancouver 4. Mutex Variables l A mutex variable is a mutual exclusion lock, allowing threads to control access to shared data. l Only one thread can hold a mutex at a time. l The threads must agree to use the mutex to protect the shared data. l Mutex variables are not managed by OS and thus very efficient (no system calls).

29 Page 29 threads CS 360, WSU Vancouver Example Diagram thread 1: do_one_thing() thread 2: do_another_thing() Global variables, etc r1 r2 shared by default r3 r3_mutex lock

30 Page 30 threads CS 360, WSU Vancouverints_mutex.c #include #include #include void lock_one_thing(int *pnum); void lock_another_thing(int *pnum); /* global (and shared) variables */ int r1 = 0, r2 = 0, r3 = 0; pthread_mutex_t r3_mutex; : continued

31 Page 31 threads CS 360, WSU Vancouver void main(int argc, char *argv[]) { pthread_t thread1, thread2; pthread_mutex_init(&r3_mutex, NULL); if (argc < 2) { printf("usage %s number\n",argv[0]); exit(1); } r3 = atoi(argv[1]); : continued

32 Page 32 threads CS 360, WSU Vancouver : pthread_create(&thread1, NULL, (void *) lock_one_thing, (void *) &r1); pthread_create(&thread2, NULL, (void *) lock_another_thing, (void *) &r2); pthread_join(thread1, NULL); pthread_join(thread2, NULL); printf(“Final Values: %d, %d\n”, r1, r2); } continued

33 Page 33 threads CS 360, WSU Vancouver void lock_one_thing(int *pnum) { int i, j, x=0; for (i = 0; i < 4; i++) { pthread_mutex_lock(&r3_mutex); r3 = r3 + (*pnum); printf(“one altered r3: %d\n”, r3); pthread_mutex_unlock(&r3_mutex); for (j = 0; j < 10000; j++) x = x + i; (*pnum)++; } } continued

34 Page 34 threads CS 360, WSU Vancouver void lock_another_thing(int *pnum) { int i, j, x=0; for (i = 0; i < 4; i++) { pthread_mutex_lock(&r3_mutex); r3 = r3 + (*pnum); printf(“another altered r3: %d\n”,r3); pthread_mutex_unlock(&r3_mutex); for (j = 0; j < 10000; j++) x = x + i; (*pnum)++; } } continued

35 Page 35 threads CS 360, WSU VancouverUsage $ ints_mutex 4 one altered r3: 4 one altered r3: 5 one altered r3: 7 one altered r3: 10 another altered r3: 10 another altered r3: 11 another altered r3: 13 another altered r3: 16 Final Values: 4, 4 $

36 Page 36 threads CS 360, WSU Vancouver 4.2. Mutex Functions int pthread_mutex_lock( pthread_mutex_t *mutex); l Lock an unlocked mutex; if already locked, the thread waits until the mutex becomes unlocked. l int pthread_mutex_trylock( pthread_mutex_t *mutex); l Lock an unlocked mutex, but if locked, do not block and return EBUSY continued

37 Page 37 threads CS 360, WSU Vancouver int pthread_mutex_unlock( pthread_mutex_t *mutex); l Unlock a mutex; if any threads are waiting to lock this mutex, one is woken up.

38 Page 38 threads CS 360, WSU Vancouver 5. Condition Variables l Synchronize threads by using events –e.g. a variable is assigned a certain value l A thread (or threads) wait for an event which is ‘signaled’ by another thread. –These events are not UNIX signals l The ‘signal’ causes the thread (or threads) to wake up. l We won’t cover the details of coding this! –This could be used effectively on the dining philosophers problem.

39 Page 39 threads CS 360, WSU Vancouver 6. Threads and UNIX l UNIX was originally designed to handle processes before shared memory multiprocessors were available. –how to add in threads to take advantage of multiple CPUs ? l A process is a ‘container’ for one or more threads –all the threads share the process’ memory address space

40 Page 40 threads CS 360, WSU Vancouver How do threads deal with... l signals? l library functions? l process management? –e.g. fork(), exec()

41 Page 41 threads CS 360, WSU Vancouver 6.1. Signals l Each thread can have its own signal mask and signal actions. l Signals can be sent to a specific thread or to the process that ‘holds’ the thread(s). –Synchronous signals get delivered to the thread that caused them (such as SEGV or SIGFPE)

42 Page 42 threads CS 360, WSU Vancouver 6.2. Library Functions l How do several threads share the same library function at the same time? –Any function that uses global variables (or statically declared variables) is suspect! l Answer: thread-safe libraries –Libraries can be made thread-safe by adding mutexes around the library function’s global variables –library functions may not be thread-safe! –Some libraries have thread-safe alternatives (ctime vs. ctime_r)

43 Page 43 threads CS 360, WSU Vancouver l What if a thread is terminated inside a library function? –e.g. in the middle of changing global data l Answer: the pthreads library includes cancellation-safe functions –they clean up upon cancellation

44 Page 44 threads CS 360, WSU Vancouver l What if a thread blocks inside a library function? l Answer: the pthreads library includes many functions which only block the thread, not the entire process –the programmer can also turn off blocking in other functions

45 Page 45 threads CS 360, WSU Vancouver 6.3. Process Management What does a fork() call from a thread do to the other threads in the containing process? Answer: the new child process contains a single copy of the thread that called fork() –What happens to mutexes? –big headaches are possible! l Guidelines: –Fork from a process with only one thread –Fork before creating additional threads –Fork only from the main (parent) thread –Hold no locks during the fork

46 Page 46 threads CS 360, WSU Vancouver What does an exec() call from a thread do to the threads in the containing process? Answer: all the threads terminate, and a new thread is created for the exec() program.


Download ppt "Page 1 threads CS 360, WSU Vancouver POSIX Threads 1. Background 2. Threads vs. Processes 3. Thread Synchronization 4. Mutex Variables 5. Condition Variables."

Similar presentations


Ads by Google