Professional Documents
Culture Documents
Synchronization
Background
The Critical-Section Problem
Petersons Solution
Synchronization Hardware
Semaphores
Classic Problems of Synchronization
Monitors
Synchronization Examples
Atomic Transactions
6.2
Objectives
To introduce the critical-section problem, whose solutions can be used to ensure the consistency of shared
data
To introduce the concept of an atomic transaction and describe mechanisms to ensure atomicity
6.3
Background
Maintaining data consistency requires mechanisms to ensure the orderly execution of cooperating
processes
Suppose that we wanted to provide a solution to the consumer-producer problem that fills all the buffers.
We can do so by having an integer count that keeps track of the number of full buffers. Initially, count is
set to 0. It is incremented by the producer after it produces a new buffer and is decremented by the
consumer after it consumes a buffer.
6.4
Producer
while (true) {
/* produce an item and put in nextProduced */
while (counter == BUFFER_SIZE)
; // do nothing
buffer [in] = nextProduced;
in = (in + 1) % BUFFER_SIZE;
counter++;
}
6.5
Consumer
while (true) {
while (counter == 0)
; // do nothing
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
counter--;
/* consume the item in nextConsumed */
}
6.6
Race Condition
6.7
Process may be changing common variables, updating table, writing file, etc
When one process in critical section, no other may be in its critical section
Each process must ask permission to enter critical section in entry section, may follow critical section with exit
section, then remainder section
6.8
Critical Section
6.9
6.10
Petersons Solution
Assume that the LOAD and STORE instructions are atomic; that is, cannot be interrupted
The variable turn indicates whose turn it is to enter the critical section
The flag array is used to indicate if a process is ready to enter the critical section. flag[i] = true implies
that process Pi is ready!
6.11
Provable that
1.
2.
3.
6.12
Synchronization Hardware
6.13
Solution to Critical-section
Problem Using Locks
do {
acquire lock
critical section
release lock
remainder section
} while (TRUE);
6.14
TestAndSet Instruction
Definition:
boolean TestAndSet (boolean *target)
{
boolean rv = *target;
*target = TRUE;
return rv:
}
6.15
critical section
lock = FALSE;
//
remainder section
} while (TRUE);
6.16
Swap Instruction
Definition:
void Swap (boolean *a, boolean *b)
{
boolean temp = *a;
*a = *b;
*b = temp:
}
6.17
Shared Boolean variable lock initialized to FALSE; Each process has a local Boolean variable key
Solution:
do {
key = TRUE;
while ( key == TRUE)
Swap (&lock, &key );
//
critical section
lock = FALSE;
//
remainder section
} while (TRUE);
6.18
6.19
Semaphore
Synchronization tool that does not require busy waiting
Semaphore S integer variable
Two standard operations modify S: wait() and signal()
Less complicated
Can only be accessed via two indivisible (atomic) operations
wait (S) {
while S <= 0
; // no-op
S--;
}
signal (S) {
S++;
}
6.20
Semaphore as
General Synchronization Tool
// initialized to 1
do {
wait (mutex);
// Critical Section
signal (mutex);
// remainder section
} while (TRUE);
6.21
Semaphore Implementation
Must guarantee that no two processes can execute wait () and signal () on the same semaphore at the
same time
Thus, implementation becomes the critical section problem where the wait and signal code are placed in the
crtical section
Note that applications may spend lots of time in critical sections and therefore this is not a good solution
6.22
Semaphore Implementation
with no Busy waiting
Two operations:
block place the process invoking the operation on the appropriate waiting queue
wakeup remove one of processes in the waiting queue and place it in the ready queue
6.23
signal(semaphore *S) {
S->value++;
if (S->value <= 0) {
remove a process P from S->list;
wakeup(P);
}
}
Operating System Concepts 8th Edition
6.24
Deadlock two or more processes are waiting indefinitely for an event that can be caused by only one of
the waiting processes
Let S and Q be two semaphores initialized to 1
P0
P1
wait (S);
wait (Q);
.
.
.
.
.
.
signal (S);
signal (Q);
wait (Q);
wait (S);
signal (Q);
signal (S);
6.25
Bounded-Buffer Problem
Dining-Philosophers Problem
6.26
Bounded-Buffer Problem
6.27
6.28
6.29
Readers-Writers Problem
Readers only read the data set; they do not perform any updates
Only one single writer can access the shared data at the same time
Several variations of how readers and writers are treated all involve priorities
Shared Data
Data set
6.30
do {
wait (wrt) ;
//
writing is performed
signal (wrt) ;
} while (TRUE);
6.31
wait (mutex) ;
readcount ++ ;
if (readcount == 1)
wait (wrt) ;
signal (mutex)
// reading is performed
wait (mutex) ;
readcount - - ;
if (readcount == 0)
signal (wrt) ;
signal (mutex) ;
} while (TRUE);
6.32
First variation no reader kept waiting unless writer has permission to use shared object
6.33
Dining-Philosophers Problem
Dont interact with their neighbors, occasionally try to pick up 2 chopsticks (one at a time) to eat
from bowl
Shared data
6.34
6.35
6.36
Monitors
A high-level abstraction that provides a convenient and effective mechanism for
process synchronization
Abstract data type, internal variables only accessible by code within the procedure
Only one process may be active within the monitor at a time
But not powerful enough to model some synchronization schemes
monitor monitor-name
{
// shared variable declarations
procedure P1 () { . }
procedure Pn () {}
Initialization code () { }
}
}
Operating System Concepts 8th Edition
6.37
6.38
Condition Variables
condition x, y;
6.39
6.40
If process P invokes x.signal (), with Q in x.wait () state, what should happen next?
Options include
Signal and wait P waits until Q leaves monitor or waits for another condition
Signal and continue Q waits until P leaves the monitor or waits for another condition
6.41
6.42
initialization_code() {
for (int i = 0; i < 5; i++)
state[i] = THINKING;
}
6.43
Each philosopher i invokes the operations pickup() and putdown() in the following sequence:
DiningPhilosophers.pickup (i);
EAT
DiningPhilosophers.putdown (i);
6.44
Variables
semaphore mutex; // (initially = 1)
semaphore next; // (initially = 0)
int next_count = 0;
body of F;
if (next_count > 0)
signal(next)
else
signal(mutex);
6.45
6.46
if (x-count > 0) {
next_count++;
signal(x_sem);
wait(next);
next_count--;
}
6.47
If several processes queued on condition x, and x.signal() executed, which should be resumed?
6.48
6.49
Synchronization Examples
Solaris
Windows XP
Linux
Pthreads
6.50
Solaris Synchronization
Implements a variety of locks to support multitasking, multithreading (including real-time threads), and
multiprocessing
Uses adaptive mutexes for efficiency when protecting data from short code segments
If lock held by non-run-state thread, block and sleep waiting for signal of lock being released
Uses readers-writers locks when longer sections of code need access to data
Uses turnstiles to order the list of threads waiting to acquire either an adaptive mutex or reader-writer lock
Priority-inheritance per-turnstile gives the running thread the highest of the priorities of the threads in its
turnstile
6.51
Windows XP Synchronization
Also provides dispatcher objects user-land which may act mutexes, semaphores, events, and timers
Events
Dispatcher objects either signaled-state (object available) or non-signaled state (thread will block)
6.52
Linux Synchronization
Linux:
Prior to kernel Version 2.6, disables interrupts to implement short critical sections
Linux provides:
semaphores
spinlocks
6.53
Pthreads Synchronization
It provides:
mutex locks
condition variables
read-write locks
spinlocks
6.54
Atomic Transactions
System Model
Log-based Recovery
Checkpoints
6.55
System Model
Assures that operations happen as a single logical unit of work, in its entirety, or not at all
6.56
Volatile storage information stored here does not survive system crashes
Not actually possible, so approximated via replication or RAID to devices with independent failure
modes
6.57
Log-Based Recovery
Log on stable storage, each log record describes single transaction write operation, including
Transaction name
Old value
New value
Log entry must reach stable storage before operation on data occurs
6.58
Using the log, system can handle any volatile memory errors
6.59
Checkpoints
Checkpoint scheme:
1.
2.
3.
Now recovery only includes Ti, such that Ti started executing before the most recent checkpoint, and all
transactions after Ti All other transactions already on stable storage
6.60
Concurrent Transactions
6.61
Serializability
6.62
Schedule 1: T0 then T1
6.63
Nonserial Schedule
If Oi, Oj consecutive and operations of different transactions & Oi and Oj dont conflict
S is conflict serializable
6.64
6.65
Locking Protocol
Locks
Shared Ti has shared-mode lock (S) on item Q, Ti can read Q but not write Q
6.66
6.67
Timestamp-based Protocols
TS can be generated from system clock or as logical counter incremented at each entry of transaction
If TS(Ti) < TS(Tj), system must ensure produced schedule equivalent to serial schedule where Ti appears
before Tj
6.68
If TS(Ti) W-timestamp(Q)
6.69
Timestamp-ordering Protocol
If TS(Ti) < R-timestamp(Q), value Q produced by Ti was needed previously and Ti assumed it would never be
produced
6.70
6.71
End of Chapter 6