Download Process Synchronization - Operating Systems - Lecture Slides and more Slides Computer Science in PDF only on Docsity!
Process Synchronization
Chapter 6
Background
- cooperating process can affect or be affected by other processes.
- Concurrent access to shared data may result in data inconsistency
- What does it mean to run two threads “concurrently”?
- Scheduler is free to run threads in any order and interleaving: FIFO, Random, …
- Dispatcher can choose to run each thread to completion of time-slice in big chunks or small chunks
- Maintaining data consistency requires mechanisms to ensure the orderly execution of cooperating processes
A B C
Multiprogramming A B C A B C B
A B C
Multiprocessing
Bounded-Buffer
#define BUFFER_SIZE 10
typedef struct {
} item;
item buffer[BUFFER_SIZE];
int in = 0;
int out = 0;
int count = 0;
Producer
while (true) {
/* produce an item and put in nextProduced */
while (count == BUFFER_SIZE); // do nothing
/* add one item */
buffer [in] = nextProduced;
in = (in + 1) % BUFFER_SIZE;
count++;
}
Accessing count concurrently
- What happens when the statements count++; count--; are performed concurrently?
- count++ could be implemented as:
register1 = count register1 = register1 + 1 count = register
- count-- could be implemented as :
register2 = count registe2 = register2 - 1 count = register
Race Condition
- Suppose counter initially set to 5. Execution of counter++ and counter-- consecutively should leave the value at 5.
- Concurrent execution could leave inconsistent data:
- S0: producer execute register1 = count {register1 = 5}
- S1: producer execute register1 = register1 + 1 {register1 = 6}
- S2: consumer execute register2 = count {register2 = 5}
- S3: consumer execute register2 = register2 - 1 {register2 = 4}
- S4: producer execute count = register1 {count = 6 }
- S5: consumer execute count = register2 {count = 4}
- Could end up with counter value of 4, 5 or 6
- There is no way to predict the relative speed of process execution, so you cannot guarantee that one will finish before the other.
Race Condition
- Race condition : The situation where several processes access – and manipulate shared data concurrently. The final value of the shared data depends upon the order of process accessing the data.
- To prevent race conditions, concurrent processes must be synchronized.
- e.g. The statements
count++; count--; must be performed atomically.
- Atomic operation means an operation that completes in its entirety without interruption.
Atomic Operations
- To understand a concurrent program, we need to know what
the underlying indivisible operations are!
- Atomic Operation: an operation that always runs to
completion or not at all
- It is indivisible: it cannot be stopped in the middle and state cannot be modified by someone else in the middle
- Fundamental building block – if no atomic operations, then have no way for threads to work together
- On most machines, memory references and assignments (i.e.
loads and stores) of words are atomic
- Many instructions are not atomic
- Double-precision floating point store often not atomic
- VAX and IBM 360 had an instruction to copy a whole array
The Critical-Section Problem
• n processes all competing to use some shared data
• Each process has a code segment, called critical
section , in which the shared data is accessed.
• Problem – ensure that when one process is executing
in its critical section, no other process is allowed to
execute in its critical section.
Solution to Critical-Section Problem
1. Mutual Exclusion - If process P i is executing in its critical
section, then no other processes can be executing in their
critical sections
2. Progress - If no process is executing in its critical section and
there exist some processes that wish to enter their critical
section, then the selection of the processes that will enter the
critical section next cannot be postponed indefinitely
3. Bounded Waiting - A bound must exist on the number of
times that other processes are allowed to enter their critical
sections after a process has made a request to enter its critical
section and before that request is granted
Assume that each process executes at a nonzero speed No assumption concerning relative speed of the N processes
Algorithm 1
- Shared variables:
- int turn ; initially turn = 0
- turn = i ⇒ Pi can enter its critical section
- Process Pi
do { while (turn != i) ; critical section turn = j ; remainder section } while (1) ;
- Satisfies mutual exclusion, but not progress
Algorithm 2
- Shared variables
- boolean flag[2] ; initially flag [0] = flag [1] = false.
- flag [i] = true ⇒ P (^) i ready to enter its critical section
- Process Pi
do { flag[i] = true; while (flag[j]) ; critical section flag [i] = false; remainder section } while (1);
- Satisfies mutual exclusion, but not progress requirement.
Synchronization Hardware
- Many systems provide hardware support for critical section
code
- Uniprocessors – could disable interrupts
- Currently running code would execute without preemption
- Generally too inefficient on multiprocessor systems
- Operating systems using this not broadly scalable
- Modern machines provide special atomic hardware
instructions
- Either test memory word and set value
- Or swap contents of two memory words
• We can use these special instructions to solve the
critical section problem.
Lock
- Suppose we have some sort of implementation of a lock
(more in a moment).
- Lock.Acquire() – wait until lock is free, then grab
- Lock.Release() – Unlock, waking up anyone waiting
- These must be atomic operations – if two threads are waiting for the lock and both see it’s free, only one succeeds to grab the lock
- Then, our critical section problem is easy:
lock.Acquire();
Critical section
lock.Release();
- Once again, section of code between Acquire() and
Release() called a “Critical Section”