From afb09551d41f2c0ac666c68dc50c14b243e2784d Mon Sep 17 00:00:00 2001 From: loshprung Date: Wed, 4 Mar 2020 11:36:12 -0800 Subject: Post-class 03/04 --- 02-26.md | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 02-26.md (limited to '02-26.md') diff --git a/02-26.md b/02-26.md new file mode 100644 index 0000000..ef1c0a5 --- /dev/null +++ b/02-26.md @@ -0,0 +1,172 @@ +[\<- Notes 02/21](02-21.md) + +--- + +# Threading Continued + +## Locking + +- Sharing Variables + - Requires mutual exclusion + - Lock/unlock to avoid a race condition +- Have one lock for each independent critical region + +- Bad Example (no synchronization): + +``` +int count = 0; + +void *update(){ //returns a pointer with no given data type + int i; + + for(i = 0; i < 1000; i++){ + count++; + } +} +``` + +- Good Example (using lock): + +``` +int count = 0; + +void *update(){ //returns a pointer with no given data type + int i; + + for(i = 0; i < 1000; i++){ + //lock + count++; + //unlock + } +} +``` + +- More real world example: + +``` +int balance = 100; //$100 + +//process 1: withdraw $20 + //read balance (i.e $100) + //write new balance (i.e $80) + +//process 2: withdraw $30 + //read balance (i.e $80) + //write new balance (i.e $50) +``` + +- In the above example, you need to use lock to avoid one process reading the balance before the other process finishes writing + +## pthread library + +- We will use the Linux pthread library + - Main information + - `man pthread` + - There are man pages for specific functions + - Include ".h" file as shown in the man page: `#include ` + - Compile using `-lpthread` + +- Operations: + +``` +#include + +pthread_t thread; + +int pthread_create( + pthread_t *restrict thread, //thread id + const pthread_attr_t *restrict attr, //attributes + void *(*start_routine)(void *), //function + void *restrict arg); //argument +``` + +- More operations: + - `void pthread_exit(void *value_ptr);` + - `int pthread_join(pthread_t thread, void **value_ptr);` + +- Example using pthreads + - Alternating threads + - Creates 3 threads + - Let the system execute them in a round-robin fashion + - Wait for them to finish at main + +``` +#include +#include //this is the library that allows for threading + +void *loopThread(void *arg); + +int main(){ + int i; + pthread_t thr[3]; + + for(i = 0; i < 3; i++){ + pthread_create(&thr[i], NULL, loopThread, (void *)i); + } + for(i = 0; i < 3; i++){ + pthread_join(thr[i], NULL); + } +} + +void *loopThread(void *arg){ + int i, j; + int threadNo = (int)arg; //cast the void pointer + + for(i = 0; i < 20; i++){ + printf("Thread %d\n", threadNo); + sleep(1); + } +} +``` + +- Functions: + +``` +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER + +//INIT +int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); + +//LOCK +int pthread_mutex_lock(pthread_mutex_t *mutex); + +//UNLOCK +int pthread_mutex_unlock(pthread_mutex_t *mutex); +``` + +- Example using mutex lock: + +``` +//Using mutex lock +//pthread_mutex_init called in main + +int count = 0; +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +void *update(){ + int i; + + while(i = 0; i < 1000; i++){ + pthread_mutex_lock(&mutex); + count++; + pthread_mutex_unlock(&mutex); + } +} +``` + +- Danger! + - When one or more threads are waiting for one another and no thread can proceed +- Example: + - One thread is waiting for itself + - Two threads are waiting for each other + - Several threads are waiting for one another in a cycle + +## Performance Considerations + +- Thread creation is expensive +- Each thread has its own stack +- Lock contention requires skills to keep many threads as possible running + +--- + +[-> Notes 03/04](03-04.md) -- cgit