Introduction to interprocess communication issues like race conditions and critical regions. Solutions such as mutual exclusion with busy waiting, sleep and wakeup, Semaphores, mutexes, monitors, barriers, and message passing.
2. Outline
Issues
How 1 process pass data to another
Making sure processes don’t get into each other’s
way while engaged in critical activity
Proper sequencing when dependencies are present
Solutions
Semaphores
Mutexes
Monitors
Message Passing
Barriers
2
3. Race Conditions
2 processes want to access shared memory at same time
Race conditions – when 2 or more processes read/write a
shared resource & final result depends on who runs correctly
Solution – mutual exclusion 3
Printer
daemon
4. Critical Regions
Part of a program where a shared resource is
accessed
Make sure no 2 processes are in critical region
at same time avoid race condition
4 conditions to provide mutual exclusion
1. No 2 processes simultaneously in critical region
2. No assumptions made about speeds or no of CPUs
3. No process running outside its critical region may
block another process
4. No process must wait forever to enter its critical
region
4
6. Supporting Mutual Exclusion
Disabling interrupts
No preemption
What if a process never enable interrupts?
Strict alternation
Strict turns
Lock variables
Single, shared variable
Reading & writing into lock is not atomic
6
7. Mutual Exclusion with Busy Waiting
Proposed solution to critical region problem
(a) Process 0, (b) Process 1
Problems?
7
8. Mutual Exclusion with Busy Waiting (Cont.)
Peterson's solution for achieving mutual exclusion 8
9. Mutual Exclusion with Busy Waiting (Cont.)
TSL – Test & set lock
Entering & leaving a critical region using TSL
assembly instruction
9
10. Issues with Busy Waiting
Waste CPU time
Unexpected effects
Process h with high priority & process l with low
priority
When h is busy waiting l will never get a chance to
leave critical region
Solution
Sleep & wakeup
10
12. Semaphores
Internal Counter capable of providing mutual
exclusion & synchronization
Counter can go Up & Down
If down() when counter is zero, thread blocks
When up() counter increases & if there are waiting
threads, one of them is released/wakeup
12
13. Semaphores (Cont.)
Integer variable to count no of wakeups saved
for future use
0 – no wakeups pending
1+ – 1 or more wakeups pending
Operations
down()
If count > 0, decrement value & continue – atomic
If count = 0, sleep – atomic
up()
If count >= 0 and no one sleeping, increment value &
continue – atomic
If count == 0, wakeup one of the sleeping threads – atomic
13
14. Semaphore Implementation If
Count Can Be Negative
down()
Decrement value
If count >= 0 continue
Else sleep
up()
Increment value
If count > 0 continue
Else wakeup one of the sleeping threads
14
15. Properties of Semaphores
Semaphores can be initialized to any integer
foo = Semaphore(100)
Binary semaphore
Initialized to 0 & used by 2+ processors to ensure only 1 can enter
critical region
After that only allowed operations are up() & down()
foo.up() = foo.signal()
foo.down() = foo.wait()
Usually can’t read current value of a semaphore
When down() is called, if counter = 0, thread is blocked &
can’t continue until another thread calls up()
When up() is called, if there are other threads waiting, 1 of
them gets unblocked 15
16. Why Semaphores?
Impose deliberate constraints that help
programmers avoid errors
Solutions using semaphores are often clean &
organized
Make it easy to demonstrate their correctness
Can be implemented efficiently on many
systems
Solutions that use semaphores are portable & usually
efficient
16
17. Example – Print A before B
Lock l
Thread 1
Print A
l.unlock();
Thread 2
l.lock();
l.lock();
Print B
17
• What if only Thread 1 get executed first?
• Fix above solution with Semaphores
18. Fixed Solution With Semaphores
Semaphore s = new S(1)
Thread 1
Print A
s.up();
Thread 2
s.down();
s.down();
Print B
18
• Is there a better way?
19. Exercise
Lock lock = new Lock();
Thread1{
Print A
lock.unlock()
}
Thread2{
lock.lock()
Print B
}
Provide 2 possible outcome of the above program
How can you use semaphore instead of Locks, such that
program will print A & B in order
19
20. Mutexes
When a semaphore’s ability to count is not needed
To enforce mutual exclusion
Implementation of mutex_lock & mutex_unlock
20
22. Monitors
Lock & Semaphores to work, code should be
well behaved
But we often forget …
Monitors are the solution
Ensure exclusive access to resources, & for
synchronizing & communicating among tasks
Natural, elegant, & efficient mechanisms
Especially for systems with shared memory
22
23. Monitors (Cont.)
Collection of variables, data structures, &
procedures (entry routines) to support high-level
synchronization
Typically, monitor data can be manipulated only
through entry routines
Only 1 task at a time can execute any entry routine
Called active task
Ensure exclusive access to resources, & for
synchronizing & communicating among tasks
Natural, elegant, & efficient mechanisms
Especially for systems with shared memory
23
24. Monitors (Cont.)
Enforce mutual exclusion by
1. Locking monitor when execution of an entry routine
begins
2. Unlocking it when active task voluntarily gives up
control of the monitor
If another task invokes an entry routine while
monitor is locked, task is blocked until monitor
becomes unlocked
Enforced by a library or operating system
24
26. Java Example
public class MyMonitor {
private final Lock lock = new ReentrantLock();
public void testA() {
lock.lock();
try {
//Some code
} finally {
lock.unlock();
}
}
public int testB() {
lock.lock();
try {
return 1;
} finally {
lock.unlock();
}
}
} 26
27. Advantages of Monitors
All synchronization code is centralized in one
location
If already implemented, users don’t need to know how
it’s implemented
Code doesn’t depend on number of processes
You don’t need to release something like a
mutex, so you can’t forget to do it
27
28. Barriers
Use of a barrier
Processes approaching a barrier
All processes but 1 blocked at barrier
Last process arrives, all are let through
E.g., matrix iterations
28
29. Multiplex
Critical section that let only N threads to enter at
a given time
Can implement using a Semaphore initialized to N
29
Source: www.codeproject.com
Disable interrupts just before entering critical region – no context switching
What happens when initially turn = 0
Sleep & Wakeup to avoid busy waiting
Counter is 0 – so consumer is ready to sleep (inside sleep()) but before it completes the function context switch happens to producer
Producer produce & try to wakeup consumer assuming it’s sleeping – but wakeup will not succeed because consumer is still not fully sleeping.
Eventually producer produce all 100 items & go to sleep. Finally both will sleep indefnetly
Act like a singleton pattern
ReentrantLock – allow current thread to reenter lock if it wants