posix threads
play

POSIX Threads In the UNIX environment a thread: Exists within a - PDF document

POSIX Threads In the UNIX environment a thread: Exists within a process and uses the process POSIX Threads resources. Has its own independent flow of control as long as its parent process exists or the OS supports it. HUJI May


  1. POSIX Threads In the UNIX environment a thread: • Exists within a process and uses the process POSIX Threads resources. • Has its own independent flow of control as long as its parent process exists or the OS supports it. HUJI • May share the process resources with other Spring 2007 threads that act equally independently (and dependently). • Dies if the parent process dies (user thread). 1 2 Pthread Attributes Why Threads • Managing threads requires fewer system A thread can possess an independent flow of resources than managing processes. control and be schedulable because it – fork() Versus pthread_create() maintains its own: • All threads within a process share the same address space . – Stack. – Registers. (CPU STATE!) – Inter-thread communication is more efficient and easier to use than inter-process communication – Scheduling properties (such as policy or priority). (IPC). – Set of pending and blocked signals. • Overlapping CPU work with I/O. – Thread specific data. • Priority/real-time scheduling. • Asynchronous event handling. 3 4 Pthread Library Creating Threads The subroutines which comprise the Pthreads • Initially, your main() program comprises a API can be informally grouped into 3 major classes: single, default thread. All other threads must – Thread management: The first class of functions be explicitly created by the programmer. work directly on threads. – Mutexes: The second class of functions deals int pthread_create ( with synchronization, called a "mutual exclusion". pthread_t *thread, – Condition variables: The third class of functions addresses communications between threads that const pthread_attr_t *attr=NULL, share a mutex. void *(*start_routine) (void *), void *arg) ; How to Compile? #include <pthread.h> gcc ex3.c –o ex3 –lpthread 5 6 1

  2. #define NUM_THREADS 5 void *PrintHello(void *index) { printf("\n%d: Hello World!\n", index); Terminating Thread Execution pthread_exit(NULL); } int main(int argc, char *argv[]) { • The thread returns from its starting pthread_t threads[NUM_THREADS]; int res, t; routine (the main routine for the initial for(t=0;t<NUM_THREADS;t++){ thread). printf("Creating thread %d\n", t); res = pthread_create(&threads[t], NULL, • The thread makes a call to the PrintHello, (void *)t); pthread_exit(status) subroutine. if (res){ printf("ERROR\n"); • The entire process is terminated due to exit(-1); } a call to either the exec or exit } subroutines. pthread_exit(NULL); } 7 8 Joining Threads Example Cont. int pthread_join(pthread_t thread, // main thread waits for the other threads void **value_ptr); for(t=0;t<NUM_THREADS;t++) { res = pthread_join(threads[t], (void **)&status); if (res) { printf("ERROR \n"); • The pthread_join() subroutine blocks the exit(-1); calling thread until the specified thread thread } printf("Completed join with thread %d status= terminates. %d\n",t, status); • The programmer is able to obtain the target } pthread_exit(NULL); thread's termination return status if specified } through pthread_exit(void *status). 9 10 Example 1 - pthread_join void *printme(void *ip) { int *i; i = (int *) ip; printf("Hi. I'm thread %d\n", *i); return NULL; } main() { Few Examples int i, vals[4]; pthread_t tids[4]; void *retval; for (i = 0; i < 4; i++) { vals[i] = i; pthread_create(tids+i, NULL, printme, vals+i); } for (i = 0; i < 4; i++) { printf("Trying to join with tid %d\n", i); pthread_join(tids[i], &retval); printf("Joined with tid %d\n", i); } 11 12 } 2

  3. Example 2 - pthread_exit void *printme(void *ip) { Output int *i; i = (int *) ip; printf("Hi. I'm thread %d\n", *i); Trying to join with tid 0 pthread_exit(NULL); Hi. I'm thread 0 } main() { Hi. I'm thread 1 int i, vals[4]; Hi. I'm thread 2 pthread_t tids[4]; Hi. I'm thread 3 void *retval; for (i = 0; i < 4; i++) { Joined with tid 0 vals[i] = i; Trying to join with tid 1 pthread_create(tids+i, NULL, printme, vals+i); } Joined with tid 1 pthread_exit(NULL); Trying to join with tid 2 for (i = 0; i < 4; i++) { Joined with tid 2 printf("Trying to join with tid %d\n", i); pthread_join(tids[i], &retval); Trying to join with tid 3 printf("Joined with tid %d\n", i); Joined with tid 3 } 13 14 } Example 3 - Exit void *printme(void *ip) { The Output int *i; i = (int *) ip; printf("Hi. I'm thread %d\n", *i); Hi. I'm thread 0 exit(0); } Hi. I'm thread 1 main() { int i, vals[4]; Hi. I'm thread 2 pthread_t tids[4]; void *retval; Hi. I'm thread 3 for (i = 0; i < 4; i++) { vals[i] = i; pthread_create(tids+i, NULL, printme, vals+i); } for (i = 0; i < 4; i++) { printf("Trying to join with tid %d\n", i); pthread_join(tids[i], &retval); printf("Joined with tid %d\n", i); } 15 16 } Output? Trying to join with tid 0 Hi. I'm thread 0 Pthread Synchronization 17 18 3

  4. Mutex Critical Section • Mutex variables are one of the primary 1 st thread 2 nd thread Balance means of implementing thread synchronization and for protecting shared 1000$ Read balance: data when multiple writes occur. 1000$ • A mutex variable acts like a "lock" protecting 1000$ Read balance: 1000$ access to a shared data resource. 1000$ Deposit: 200$ • The basic concept of a mutex as used in Pthreads is that only one thread can lock (or 1000$ Deposit: 200$ own) a mutex variable at any given time . 1200$ Update balance 1200$ Update balance 19 20 Creating and Destroying Mutex Work Flow Mutex variables must be declared with type A typical sequence in the use of a mutex is as pthread_mutex_t , and must be initialized before follows: they can be used: • Create and initialize a mutex variable. – Statically, when it is declared. For example: • Several threads attempt to lock the mutex. pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER ; • Only one succeeds and that thread owns the – Dynamically, mutex. pthread_mutex_init(mutex, attr) • The owner thread performs some set of actions. This method permits setting mutex object attributes (for • The owner unlocks the mutex. default setting use NULL). • Another thread acquires the mutex and repeats pthread_mutex_destroy(mutex) should be the process. used to free a mutex object when is no longer needed. • Finally the mutex is destroyed. 21 22 Locking Mutex Unlock Mutex • The pthread_mutex_lock(mutex) • pthread_mutex_unlock(mutex) routine is used by a thread to acquire a will unlock a mutex if called by the lock on the specified mutex variable. owning thread. Calling this routine is • If the mutex is already locked by required after a thread has completed its use of protected data. another thread, this call will block the calling thread until the mutex is • An error will be returned if: unlocked. – If the mutex was already unlocked. – If the mutex is owned by another thread. 23 24 4

  5. Fixed Example Example pthread_mutex_lock (&mut); Thread 2: Thread 1: a = counter; a++; a = counter; counter = a; b = counter; pthread_mutex_unlock (&mut); a++; pthread_mutex_lock (&mut); b--; b = counter ; counter = a; b--; counter = b; counter = b; pthread_mutex_unlock (&mut); 25 26 Conditional Variables Condition Variables • While mutexes implement synchronization by • Useful when a thread needs to wait for a controlling thread access to data, condition certain condition to be true. variables allow threads to synchronize based • In pthreads , there are four relevant procedures involving condition variables : upon the actual value of data. – pthread_cond_init(pthread_cond_t *cv, • Without condition variables, The programmer NULL); would need to have threads continually polling – pthread_cond_destroy(pthread_cond_t *cv); (usually in a critical section), to check if the – pthread_cond_wait(pthread_cond_t *cv, condition is met. pthread_mutex_t *lock); • A condition variable is a way to achieve the same – pthread_cond_signal(pthread_cond_t *cv); goal without polling (a.k.a. busy wait) 27 28 Creating and Destroying pthread_cond_wait Conditional Variables • Condition variables must be declared with type • pthread_cond_wait(cv, lock) is called pthread_cond_t , and must be initialized by a thread when it wants to block and wait before they can be used. for a condition to be true. • Statically, when it is declared. For example: • It is assumed that the thread has locked the pthread_cond_t myconvar = mutex indicated by the second parameter. PTHREAD_COND_INITIALIZER; • The thread releases the mutex, and blocks • Dynamically until awakened by a pthread_cond_signal() call from another pthread_cond_init(cond, attr); thread. Upon successful initialization, the state of the condition variable becomes initialized. • When it is awakened, it waits until it can acquire the mutex, and once acquired, it • pthread_cond_destroy(cond) should be returns from the pthread_cond_wait() used to free a condition variable that is no call. longer needed. 29 30 5

Recommend


More recommend