Professional Documents
Culture Documents
Chapter 6 - Synchronization Tools - Part 2
Chapter 6 - Synchronization Tools - Part 2
Chapter 6 - Synchronization Tools - Part 2
Synchronization
Tools
Edited by
Ghada Mohammed S AlOsaimi
CS Lecturer, CCIS, IMISIU
Outline
Mutex Locks
Semaphores
Liveness
Process
Management
Storage
Management
2
Objectives
Demonstrate how mutex locks, semaphores, and condition variables
Evaluate tools that solve the critical-section problem in low-. Moderate-, and high-contention scenarios
3
Mutex Locks
Previous solutions (HW-based) are complicated and generally inaccessible to application programmers
OS designers build software tools to solve critical section problem
Simplest one is mutex lock, a higher-level SW-based tool
Protect a critical section by first acquire() a lock then release() the lock
Boolean variable indicating if lock is available or not, with initial value true
Calls to acquire() and release() must be atomic
Usually implemented via hardware atomic instructions such as compare-and-swap
4
Mutex Locks (cont.)
No other thread can own that mutex until the owning thread unlocks that mutex
Threads must "take turns" accessing protected data
Very often example; the action performed by a thread owning a mutex is the updating of global variables
Safe way to ensure that when several threads update the same variable, the final value is the same as what it would be
if only one thread performed the update
5
Mutex Locks (cont.)
Thread 1 Thread 2
A typical sequence in the use of a mutex is as follows
Acquire mutex lock Acquire mutex lock
Create and initialize a mutex variable
6
Solution to Critical-section Problem Using Locks
7
Mutex Locks (cont.)
8
Mutex Locks in Pthreads (POSIX Threads)
Creates and initializes a new mutex object, then sets its attributes according to the mutex attributes object (attr)
pthread_mutex_lock( )
Used by a thread to acquire a lock on the specified mutex variable
If the mutex is already locked by another thread, the call will block the calling thread until the mutex is unlocked
pthread_mutex_trylock( )
Attempt to lock a mutex
If the mutex is already locked, the routine will return immediately
This routine may be useful in preventing deadlock conditions, as in a priority-inversion situation
pthread_mutex_unlock( )
Unlock a mutex if called by the owning thread
Calling this routine is required after a thread has completed its use of protected data if other threads are to acquire the
mutex for their work with the protected data
11
Example – No Mutex Locks
12
Example – With Mutex Locks
13
Another Example
14
Semaphore
16
Counting Semaphore
17
Semaphore Implementation
Must guarantee that no two processes can execute wait()and signal()on the same semaphore at the same time
Thus, the implementation becomes the critical section problem where the wait and signal code are placed in the critical
section
Could now have busy waiting as mutex lock critical section implementation
But implementation code is short
Little busy waiting if critical section rarely occupied
Note that applications may spend lots of time in critical sections and therefore this is not a good solution
Better Solution !
Implement semaphore with no busy waiting
18
Semaphore Implementation with no Busy waiting
To overcome the need for busy waiting, we can modify the definition of the wait() and signal() semaphore operations
When a process executes wait() operation and finds that semaphore value is not positive, it must wait
However, rather than engaging in busy waiting, the process can block() itself
The block operation places a process into a waiting queue associated with the semaphore, and the state of the
process is switched to the waiting state ; with each semaphore there is an associated waiting queue
Then control is transferred to the CPU scheduler, which selects another process to execute
The process that is suspended, waiting on a semaphore S, should be restarted when some other process executes a
signal() operation
Restarting process is done by a wakeup(), which changes the process to the ready state
20
Implementation with no Busy waiting (Cont.)
wait(semaphore *S) {
S->value--;
if (S->value < 0) {
add this process to S->list;
block();
}
}
signal(semaphore *S) {
S->value++;
if (S->value <= 0) {
remove a process P from S->list;
wakeup(P);
}
}
21
POSIX Semaphore Functions
Initializing semaphores
Decreasing the count of a semaphore
Increasing the count of a semaphore
Destroying semaphores
22
POSIX Semaphore Functions (cont.)
All of the POSIX semaphore functions return -1 to indicate an error and 0 on success
sem_init function
initializes the semaphore sem to have the value value
value parameter cannot be negative
pshared value:
0: only threads of the creating process can use the semaphore
Non-0: other processes can use the semaphore (i.e. the process that initializes it and by children of that process)
sem_wait
Standard semaphore wait operation
If the semaphore sem is 0, the sem_wait blocks unit it can successfully decrement the semaphore value
23
POSIX Semaphore Functions (cont.)
sem_trywait
It is similar to sem_wait except that instead of blocking when attempting to decrement a zero-valued semaphore, it
returns -1
Test a semaphore’s current condition
sem > 0: thread acquires lock ; sem == 0: thread returns
sem_post
Standard semaphore signal operation
sem > 0: no threads were blocked on this semaphore, the semaphore value is incremented
sem == 0: one blocked thread will be allowed to run
24
Basic Synchronization Patterns
1 | Signaling
Represents the simplest use for a semaphore which is signaling
One process/thread sends a signal to another process/thread to
indicate that something has happened
Pseudo-code describes the solutions
25
Basic Synchronization Patterns (cont.)
2 | Rendezvous
Generalize the signal pattern so that it works both ways; Process One has to wait for Process Two and vice versa
Pseudo-code describes the problem:
To guarantee that a1 happens before b2 and b1 happens before a2; need to use two semaphores
Pseudo-code describes the tried solution:
26 Deadlock: While working on the previous problem, you might have tried something like this
Basic Synchronization Patterns (cont.)
2 | Rendezvous
Pseudo-code describes the solution 1:
27
Basic Synchronization Patterns (cont.)
3 | Mutual exclusion
Use a semaphore to guarantee that only one process/thread accesses a shared memory (or global variables at a time
Pseudo-code describes the solution:
28
POSIX Semaphore – Critical Section Problem
29
Problems with Semaphores
Incorrect use of semaphore can result in timing errors that are difficult to detect, since these errors happen only if particular
execution sequences take place, and these sequences do not always occur
Examples: suppose that a program replaces signal(mutex) with wait(mutex)
These – and others – are examples of what can occur when semaphores and other synchronization tools are used incorrectly
30
Liveness
Processes may have to wait indefinitely while trying to acquire a synchronization tool such as a mutex lock or semaphore
Waiting indefinitely violates the progress and bounded-waiting criteria discussed at the beginning of this chapter
Liveness refers to a set of properties that a system must satisfy to ensure processes make progress
Indefinite waiting (busy wait loop) and deadlock are examples of a liveness failure
Deadlock – two or more processes are waiting indefinitely for an event that can be caused by only one of the waiting
processes
P P1
Let S and Q be two semaphores initialized to 1 wait(S); wait(Q);
Consider if P0 executes wait(S) and P1 wait(Q) wait(Q); wait(S);
... ...
When P0 executes wait(Q), it must wait until P1 executes signal(Q) signal(S); signal(Q);
signal(Q); signal(S);
However, P1 is waiting until P0 execute signal(S)
Since these signal() operations will never be executed, P0 and P1 are deadlocked
31
Liveness (cont.)
To prevent this from occurring, a priority inheritance protocol is used. This simply allows the priority of the highest thread
waiting to access a shared resource to be assigned to the thread currently using the resource. Thus, the current owner of the
resource is assigned the priority of the highest priority thread wishing to acquire the resource.
32