synchronization
play

Synchronization Disclaimer: some slides are adopted from the book - PowerPoint PPT Presentation

Synchronization Disclaimer: some slides are adopted from the book authors slides with permission 1 Recap Race condition A situation when two or more threads read and write shared data at the same time Correctness depends on the


  1. Synchronization Disclaimer: some slides are adopted from the book authors’ slides with permission 1

  2. Recap • Race condition – A situation when two or more threads read and write shared data at the same time – Correctness depends on the execution order • Critical section – Code sections of potential race conditions • Mutual exclusion – If a thread executes its critical section, no other threads can enter their critical sections 2

  3. Recap • Peterson’s algorithm – Software-only solution • Turn based – Pros • No hardware support • Satisfy all requirements – Mutual exclusion, progress, bounded waiting – Cons • Complicated • Assume program order • May not work on out-of-order processors 3

  4. Today • Synchronization instructions • Lock – Spinlock – Mutex 4

  5. Lock • General solution – Protect critical section via a lock – Acquire on enter, release on exit do { acquire lock; critical section release lock; remainder section } while(TRUE); 5

  6. How to Implement a Lock? • Unicore processor – No true concurrency one thread at a time – Threads are interrupted by the OS • scheduling events: timer interrupt, device interrupts • Disabling interrupt do { – Threads can’t be disable interrupts ; interrupted critical section enable interrupts ; remainder section } while(TRUE); 6

  7. How to Implement a Lock? • Multicore processor – True concurrency • More than one active threads sharing memory – Disabling interrupts don’t solve the problem • More than one threads are executing at a time • Hardware support – Synchronization instructions • Atomic test&set instruction • Atomic compare&swap instruction • What do we mean by atomic ? – All or nothing 7

  8. TestAndSet Instruction • Pseudo code boolean TestAndSet (boolean *target) { boolean rv = *target; *target = TRUE; return rv: } 8

  9. Spin lock using TestAndSet void init_lock (int *mutex) { int mutex; *mutex = 0; init_lock (&mutex) ; } do { void lock (int *mutex) { lock (&mutex); while(TestAndSet(mutex)) critical section ; unlock (&mutex) ; } remainder section void unlock (int *mutex) } while(TRUE); { *mutex = 0; } 9

  10. CAS (Compare & Swap) Instruction • Pseudo code int CAS(int *value, int oldval, int newval) { int temp = *value; if (*value == oldval) *value = newval; return temp; } 10

  11. Spin lock using CAS void init_lock (int *mutex) { int mutex; *mutex = 0; init_lock (&mutex) ; } do { void lock (int *mutex) { while(CAS(&mutex, 0, 1) != 0); lock (&mutex); } critical section unlock (&mutex) ; void unlock (int *mutex) { *mutex = 0; remainder section } } while(TRUE); 11

  12. What’s Wrong With Spin locks? • Very wasteful – Waiting thread continues to use CPU cycles – While doing absolutely nothing but wait – 100% CPU utilization, but no useful work done – Power consumption, fan noise, … • Useful when – You hold the lock only briefly • Otherwise – A better solution is needed 12

  13. Mutex – Blocking Lock • Instead of spinning – Let the thread sleep • There can be multiple waiting threads – In the meantime, let other threads use the CPU – When the lock is released, wake-up one thread • Pick one if there multiple threads were waiting 13

  14. void mutex_init (mutex_t *lock) More reading: mutex.c in Linux { lock->value = 0; list_init(&lock->wait_list); Thread waiting list spin_lock_init(&lock->wait_lock); To protect waiting list } void mutex_lock (mutex_t *lock) { … while(TestAndSet(&lock->value)) { … … … … … } … } void mutex_unlock (mutex_t *lock) { … lock->value = 0; … … … 14 }

  15. void mutex_init (mutex_t *lock) More reading: mutex.c in Linux { lock->value = 0; list_init(&lock->wait_list); Thread waiting list spin_lock_init(&lock->wait_lock); To protect waiting list } void mutex_lock (mutex_t *lock) { … while(TestAndSet(&lock->value)) { Thread state change current->state = WAITING; list_add(&lock->wait_list, current); Add the current thread to the … waiting list schedule(); Sleep or schedule another thread … } … } void mutex_unlock (mutex_t *lock) { … lock->value = 0; … … … 15 }

  16. void mutex_init (mutex_t *lock) More reading: mutex.c in Linux { lock->value = 0; list_init(&lock->wait_list); Thread waiting list spin_lock_init(&lock->wait_lock); To protect waiting list } void mutex_lock (mutex_t *lock) { spin_lock(&lock->wait_lock); while(TestAndSet(&lock->value)) { Thread state change current->state = WAITING; list_add(&lock->wait_list, current); Add the current thread to the … waiting list schedule(); Sleep or schedule another thread … } spin_unlock(&lock->wait_lock); } void mutex_unlock (mutex_t *lock) { … lock->value = 0; … … … 16 }

  17. void mutex_init (mutex_t *lock) More reading: mutex.c in Linux { lock->value = 0; list_init(&lock->wait_list); Thread waiting list spin_lock_init(&lock->wait_lock); To protect waiting list } void mutex_lock (mutex_t *lock) { spin_lock(&lock->wait_lock); while(TestAndSet(&lock->value)) { Thread state change current->state = WAITING; list_add(&lock->wait_list, current); Add the current thread to the spin_unlock(&lock->wait_lock); waiting list schedule(); Sleep or schedule another thread spin_lock(&lock->wait_lock); } spin_unlock(&lock->wait_lock); } void mutex_unlock (mutex_t *lock) { … lock->value = 0; … … … 17 }

  18. void mutex_init (mutex_t *lock) More reading: mutex.c in Linux { lock->value = 0; list_init(&lock->wait_list); Thread waiting list spin_lock_init(&lock->wait_lock); To protect waiting list } void mutex_lock (mutex_t *lock) { spin_lock(&lock->wait_lock); while(TestAndSet(&lock->value)) { Thread state change current->state = WAITING; list_add(&lock->wait_list, current); Add the current thread to the spin_unlock(&lock->wait_lock); waiting list schedule(); Sleep or schedule another thread spin_lock(&lock->wait_lock); } spin_unlock(&lock->wait_lock); } void mutex_unlock (mutex_t *lock) { … lock->value = 0; if (!list_empty(&lock->wait_list)) Someone is waiting for the lock wake_up_process(&lock->wait_list) Wake-up a waiting thread … 18 }

  19. void mutex_init (mutex_t *lock) More reading: mutex.c in Linux { lock->value = 0; list_init(&lock->wait_list); Thread waiting list spin_lock_init(&lock->wait_lock); To protect waiting list } void mutex_lock (mutex_t *lock) { spin_lock(&lock->wait_lock); while(TestAndSet(&lock->value)) { Thread state change current->state = WAITING; list_add(&lock->wait_list, current); Add the current thread to the spin_unlock(&lock->wait_lock); waiting list schedule(); Sleep or schedule another thread spin_lock(&lock->wait_lock); } spin_unlock(&lock->wait_lock); } void mutex_unlock (mutex_t *lock) { spin_lock(&lock->wait_lock); lock->value = 0; if (!list_empty(&lock->wait_list)) Someone is waiting for the lock wake_up_process(&lock->wait_list) Wake-up a waiting thread spin_unlock(&lock->wait_lock); 19 }

Recommend


More recommend