Slides Synchronization I
Slides Synchronization I
Synchronization
1
Objectives and Outline
2
Synchronization: Concurrency, shared data, race condition
Background
count
Producer Consumer
Shared Buffer
Producer Consumer
5
Synchronization: Concurrency, shared data, race condition
6
Synchronization: Concurrency, shared data, race condition
7
Synchronization: Concurrency, shared data, race condition
Race Condition
register1 Count
PRODUCER (count++)
56 654
register1 = count
register1 = register1 + 1
register2 count = register1
54
CONSUMER (count--)
register2 = count
register2 = register2 – 1
CPU count = register2
Main Memory
8
Synchronization: Concurrency, shared data, race condition
9
Synchronization: Concurrency, shared data, race condition
Race condition
10
Synchronization: Concurrency, shared data, race condition
Race condition
• In previous example:
– For consistent result (5), either count++ should be
executed and finished first, or count-- should be executed
and finished. Not interleaved.
• To avoid race condition we need to enforce non-interleaved
access (atomic) to shared data.
• We need synchronization (coordination) of threads/processes
while accessing shared data.
11
Synchronization: Critical section problem
Update X
Update X
Update Y
Update Y
Update Y
13
Synchronization: Critical section problem
Program structure
exit section
Entry section will allow only one process to enter and execute critical section code.
14
Synchronization: Critical section problem
16
Synchronization: Critical section problem
do {
} while (1)
19
Synchronization: Pure software solutions: Peterson’s solution
Synchronization Hardware
21
Synchronization: Hardware support for synchronization: Us of a lock variable via special instructions
Locks
Thread 1 Thread 2
Synchronization Hardware
24
Synchronization: Hardware support for synchronization: Special instruction
TestAndSet Instruction
• is a machine/assembly instruction.
TestAndSet REGISTER, LOCK;
25
Synchronization: Hardware support for synchronization: Special instruction
do {
while ( TestAndSet (&lock)) entry section
; // do nothing
// critical section
exit_section
lock = 0;
// remainder section
} while (TRUE);
26
Synchronization: Hardware support for synchronization: Special instruction
In assembly
entry_section:
TestAndSet REGISTER, LOCK;
CMP REGISTER, #0 entry section code
JNE entry_section;
RET
exit_section:
move LOCK, #0 exit section code
RET
main:
..
call entry_section;
execute critical region;
call exit_section;
27
Synchronization: Hardware support for synchronization: Special instruction
28
Synchronization: Hardware support for synchronization: Special instruction
entry_section
exit_section
29
Synchronization: Hardware support for synchronization: Special instruction
Comments
30
Synchronization: Hardware support for synchronization: Special instruction
// critical section
exit section code
j = (i + 1) % n;
while ((j != i) && !waiting[j]) // search for a process waiting
j = (j + 1) % n; // j was not interested
if (j == i) // no other process wants to enter CS
lock = 0; // set lock to 0
else // there is a process j that is waiting in while loop
waiting[j] = FALSE; // process j will be in CS; lock still 1
// remainder section
} while (TRUE);
31
Synchronization: Mutex locks (high-level tools)
Mutex locks
• We can put these entry and exit section codes into lock() and
unlock() functions in a library/kernel. Then we have a lock
implementation. It is also called mutex lock (mutual exclusion
lock)
• Applications will not be directly using HW instructions; instead
lock implementation will use these HW instructions.
• Applications will just call mutex_lock() and mutex_unlock()
functions.
32
Synchronization: Mutex locks
Locks
35
Synchronization: Mutex locks: spin locks
Spin Locks
Process A running in kernel mode Process B running in kernel mode
(i.e., executing kernel code shown) (i.e. executing kernel code shown)
CPU 1 CPU 2
36
Synchronization: Mutex locks (high-level tools)
37
Synchronization: Condition variables
Condition Variables
• mutex variables (locks) can be used to solve the critical section
problem (exclusive access).
• But there are other synchronization needs and problems.
– For example, we may want to block (sleep, wait) a thread
until some event / condition happens. How can we do that?
• Condition variables are for such cases.
• A condition variable (cv) is an object/variable (ADT) that can
be used to cause a thread to sleep until a condition happens.
– Internally, a cv has a waiting queue associated with it.
– A cv has two operations that can be performed on it: wait()
and signal()
38
Synchronization: Condition variables
Condition Variables
39
Synchronization: Condition variables
Example 1
global variables
int count = 0; // shared state between threads
pthread_mutex_t lock; // lock variable
pthread_cond_t cv; // condition variable
40
Synchronization: Condition variables
Example 1
cond_wait() body first releases the lock; then sleeps on
the cv queue. When waken up (signaled), it is removed
from cv queue. Then it tries to get the lock again (added
to the lock queue). when it has the lock, cond_wait()
returns.
// executed by thread 1
void * function1 (void *p) // executed by thread 1
{
// assume waited condition is “count == 100”
pthread_mutex_lock (&lock); // lock the lock
while (count < 100)
pthread_cond_wait (&cv, &lock);
!"#$%&%"#'(!")#&'*+',--.'%/'0'123$%!0&3'&40&'%#!5)$3/'/4023$'602%0753/8''
41
Synchronization: Condition variables
Example 1
// executed by thread 2
void *function2 (void *p) {
pthread_mutex_lock (&lock); // get lock
while (count < 100)
count += 1; // changing shared data (count)
// waited condition happened
pthread_cond_singal (&cv); // signal and continue
// signaling thread still has the lock.
// waken up thread is moved from cv wait-queue
// to lock wait-queue.
pthread_mutex_unlock(&lock) // release the lock now
}
42
Synchronization: Condition variables
Example 2
43
Synchronization: Condition variables
Example 2
...
int k // local variable of the thread – needed instances
while (1) {
k = generateRandomValue(1,100)// between 1 and 100
allocate_resources (k);
// use resources - may take a while
deallocate_resources (k);
}
44
Synchronization: Condition variables
Example 2
45
Synchronization: Condition variables
Example 2
46
Synchronization: Condition variables
Then it will loop and check the condition again while holding the
lock. If the condition did not happen yet, the thread will call
pthread_cond_wait() again. The call will cause the thread to
release the lock and sleep on the condition variable again.
47
Synchronization: Condition variables
Tips
• Always wait in a while loop for condition to be true (unless you
are sure if statement is needed instead of while). This is safer
and more modular.
• If there are multiple threads waiting, just one signal() may not
wake up the correct thread in some cases. In those cases, use
of broadcast() can simplify coding.
– broadcast() wakes up all threads waiting on the condition
variable. Each thread, one by one, will check the condition
again, and if condition is not true, will wait on condition
variable queue again.
• Have the lock while accessing shared variables.
48
Synchronization: Semaphores: Definition
Semaphore
• wait (S):
if S positive
S-- and return
else
block here (until somebody wakes you up; then return)
• signal(S):
if there is a process waiting
wake it up and return
else
S++ and return
50
Synchronization: Semaphores: Definition
Comments
51
Synchronization: Semaphores: Definition
52
Synchronization: Semaphores: Usage
Semaphores usage:
critical section problem
• A semaphore variable should be defined, initialized to 1.
• Will be shared by multiple processes (say 𝑁) processes.
• Each process 𝑖, 1 ≤ 𝑖 ≤ 𝑁, is structured as follows:
do {
wait (mutex);
// critical section code
signal (mutex);
// remainder section
} while (1);
53
Synchronization: Semaphores: Usage
Semaphores usage:
critical section problem
Process 0 Process 1
do {
do {
wait (mutex);
wait (mutex);
// Critical Section
// Critical Section
signal (mutex);
signal (mutex);
// remainder section
// remainder section
} while (TRUE);
} while (TRUE);
54
Synchronization: Semaphores: Usage
Semaphore usage:
other synchronization problems
P0 P1
… … Assume we definitely want to
S1; S2; have statement S1 executed
…. ….
before statement S2.
semaphore x = 0; // initialized to 0
P0 P1
… …
solution: S1; wait (x);
signal (x); S2;
…. ….
55
Synchronization: Semaphores: Usage
Producer Consumer
do { do {
// produce item wait (Full_Cells);
… ….
put item into buffer remove item from buffer
.. ..
signal (Full_Cells); …
} while (TRUE);
} while (TRUE);
56
Synchronization: Semaphores: Usage
57
Synchronization: Semaphores: Implementation
Semaphore Implementation
58
Synchronization: Semaphores: Implementation
Semaphore Implementation
}
}
59
Synchronization: Semaphores: Implementation
60
Synchronization: Semaphores: POSIX Semaphore API
POSIX Semaphores
Named Semaphores
Unnamed Semaphores sem_t * Sp;
sem_t S; char * sname = "semname1";
Sem S=1;
P0 P1
Sem Q=1;
wait (S); wait (Q);
wait (Q); wait (S);
…. ….
signal (S); signal (Q);
signal (Q); signal (S);
62
Synchronization: Semaphores: Potential problems
64
References
65