more on concurrency

Message Queues

[http://www.linuxtutorial.info/modules.php?name=Tutorial&pa
geid=292]
Monitors:




Previous examples had the critical section inside the
process
Idea is to put the critical section inside of a construct
called a monitor.
Monitor has entry points (like methods) BUT only
one entry call can be processed at a time.
Supported in concurrent languages: Modula-2, -3,
Concurrent Pascal, Concurrent C, CSP, also,
partially, Java, also part of the .NET Framework
library.
Generic outline:
Monitor monitor_name
:
monitor variables
:
entry entry1;
:
:
end entry
entry entry2
:
:
end entry;
:
etc;
:
end Monitor;


If proc1 is executing in a monitor entry and proc2
calls an entry then proc2 waits until proc1 finishes.
A monitor has two condition variables – special
variables that define wait and wakeup protocols. i.e.
Suppose x is a condition variable.


x.wait forces a process to wait
x.signal wakes a process in a wait state because of an
x.wait.
Bounded Buffer problem:
Monitor buffMgmt
int first=0, last=0, occupied=0, N // monitor variables
int [N] buffer
condition empty, full;
// condition variables
entry putin(x);
if (occupied == N)
full.wait
buffer[first] = x
first = (first+1) % N;
occupied++
empty.signal
end putin
entry getout()
data temp;
if (occupied == 0)
empty.wait
temp = buffer(last);
last = (last + 1) % N
occupied-full.signal
return temp
end




Do a Monitor solution to the readers and writers
problem
Recall the conditions to the R/W problem:
If a reader wants access, deny iff a writer is active
if a writer wants access, deny only iff a reader or
writer is active


Note: this could cause starvation of writers if there are
many readers
Could replace 1 above with: if a reader wants access,
deny iff a writer is active or a writer is waiting.
Monitor readers_writers
int count //number of readers
condition readallowed, writeallowed
boolean writing
data shared
entry startwrite
if (count != 0) or (writing)
writeallowed.wait
writing = true
end entry
entry donewriting
writing = false
if (Q for readallowed not empty)
readallowed.signal
else
writeallowed.signal
end entry
entry startread
if writing or (Q for writeallowed not empty)
readallowed.wait
count++
readallowed.signal
end entry
entry donereading
count—
if count == 0
writeallowed.signal
end entry

Now look at the Java implementation of the readers
and writers problem. It’s a little different.






Ada
[http://www.acm.org/sigs/sigada]
[http://www.adaic.org/]
[http://www.adaic.org/atwork/index.html]
The language is named after Ada Byron, Countess
of Lovelace, who was the first published computer
programmer and daughter of the poet Lord Byron.
All previous solutions were centralized. Ada is more
of a distributed/network solution.






Controls computers in nearly all new aircraft
Nearly all air traffic control systems
hi-speed railroads and urban subway systems
electronic funds and banking
communication and navigation satellites.
Steel mills, industrial robots, medical electronics,
telecommunications



Two types of tasks:
caller: calls entry points in a server
server: may (or may not) accept calls


calls not processeduntil accept has been issued.
called a rendezvous.
Ada can be used to simulate a semaphore.
procedure mutexc is
task semaphore is
entry wait
entry signal
end semaphore
task body semaphore is
begin
loop
accept wait
accept signal
end loop
end semaphore
task Pi
task body Pi is
begin
loop
:
:
wait
critical section
signal
:
:
end loop
end Pi
Select statement
Select
when cond1 => accept entry1
do stuff
end entry
or when cond2 => accept entry2
do stuff
end entry
or when ……..
:
:
else
do stuff
end select






Each condition is a guard and evaluates to T or F.
Several may be true
an accept for which the corresponding guard is True
is open.
An open accept is chosen arbitrarily (not by Ada)
from the list of open accepts for which entry calls
have been made.
The chosen accept is then processed.
No such accepts => the else option is taken
Ada Solution to the readers and writers problem
task reader
task body reader is
begin
loop
:
:
startread
read stuff
finishread
:
:
end loop
end reader
task writer
task body writer
somedata : anytype
begin
loop
:
:
writeshared(x)
:
:
end loop
end writer
task readerswriters is
entry startread
entry finishread
entry writetoshared
end;
task body readerswriters is
numreaders : Integer
begin
numreaders = 0
loop
select
when writetoshared’count = 0
accept startread
numreaders = numreaders + 1
end startread
or
accept finishread
numreaders = numreaders – 1
end finishread
or
when numreaders = 0
accept writeshared(x : anytype)
write x to shared area
end writeshared
end select
end loop
end






Review of concurrency constructs
Program critical sections, software implementations
semaphores
monitor
Java Synchronized methods
ada
Deadlock


Definition: Deadlock (also deadly embrace) occurs
when two or more processes in a wait state are each
waiting for a resource held by one of the other
processes in the wait state.
Ex:



Previously failed attempts at mutual exclusion
processes write to a shared buffer, filling it. If buffer hits
limit before processes are done, deadlock occurs.
Database examples if two apps each hold a record and
want what the other has.
Four necessary conditions for deadlock to occur:

Mutual Exclusion


Hold and Wait


process holds allocated resources while requesting more.
No preemption


process claims exclusive control of required resource.
Resources cannot be taken away until process is finished
with them.
Circular wait

Circular chain of processes exist in which each process
holds at least 1 resource requested by the next process in
the chain.
Four areas of deadlock study:

Prevention


Avoidance


Use algorithms to monitor resource allocation so that
deadlock won’t happen.
Detection


Create an environment where deadlock is impossible.
Determine when deadlock has occurred.
Recovery

What to do when deadlock occurs.
Handling Deadlocks:




Implement a protocol to prevent or avoid deadlocks.
Allow deadlocks to occur, then detect and recover.
Ignore and leave it to the user.
Third option is most common (Linux and Windows
use this).

Prevention


Mutual Exclusion?


Eliminate one of the previously mentioned necessary
conditions, but which one?
Can generate incorrect results.
Hold and Wait?

Could require processes to request and get all resources at
the same time. Thus, can’t hold resources while
requesting more. Not always practical. Resources may be
held much earlier than needed.

No Preemption?


Take resources away might result in loss of work. Process
will have to be restarted.
Circular Wait?



Request resources in some numerical order?
Awkward
May not be the order in which they are needed.
Conclusion

Prevention is not practical or at least cannot be done
without severe side effects.
Detection

Resource allocation graph example.



Specifies which process is waiting for what resource (request
edge) and what resource is allocated to which process
(assignment edge). Example below:
RiPj means resource Ri is allocated to process Pj
Pj Ri means process Pj is waiting for a resource of type Ri




No cycle  no deadlock.
Cycle  deadlock possible.
If each resource group contains just one resource
then cycle  deadlock.
Need cycle detection algorithms of COMP SCI 242
Deadlock avoidance algorithms
Resource Allocation Graph Algorithm:




Add a claim edge (dotted line in graph on the next
slide) to the graph. Represents that a process may
request a resource.
Process makes a request  claim edge converted to
a request edge or assignment edge, depending on
whether the resource was allocated.
Safe state  no cycles in the graph.
Unsafe state  a cycle exists (NOTE: does NOT
mean deadlock exists – only that it could happen.
P1
P2
P3
R1



R2
R3
Above case is safe: P1 or P2 can finish.
If P2 requests R1, convert the claim edge to a request edge.
P2 is now waiting but the system is still safe since P1 can still
finish and release the R1 resource. OS has little to do here.
The request is made.
However, if instead P3 requests R2, it can be allocated but
then a cycle exists and the system is unsafe. Thus, although
R2 could be allocated, it is not. NOTE: Deadlock has not
occurred but it could if P1 and P3 assert their claims.




Banker’s Algorithm
Applicable where there are multiple resources of a
common type. Processes request 1 or more resources
of a type, but don’t care which they get.
Each process declares the maximum number of
resources of each type it needs.
Distinguishes between a safe and an unsafe state.



Safe state: Resource situation is such that all
existing processes can finish, regardless of
future requests.
Unsafe state: It’s possible that a sequence of
requests could deadlock the system – even if
requests are denied. Deadlock may occur.
Goal: No request should cause the system to
change from a safe to unsafe state.





Data Structures:
Available[i] – number of available resources
of type Ri.
Max[i] [j] – contains the maximum number of
resources Pi can request of type Rj.
Allocation[i] [j] – contains the number of
resources of type Rj allocated to Pi.
Need[i] [j] = Max[i] [j] – Allocation[i] [j]





Safety algorithm:
Initialize Work[j] = Available[j] for all j=1 to #resource types
and Finish[i] = false for all i=1 to #processes
Find an i where Finish[i] is false and Need[i] <= Work. i.e.
find a process whose need for each type is less than the #
available for that type. NOTE: Need[i] and Work are both
vectors and <= means that the inequality holds for ALL
elements in the vector. Do step 4.
Work=Work+Allocation and Finish[i]=true. Repeat from
Step 2.
If Finish[i] is True for all i, the system is safe. Else an unsafe
state.
Examples:
Max
Available
A B C
A B C
A B C
P0
0 1 0
7 5 3
3 3 2
P1
2 0 0
3 2 2
P2
3 0 2
9 0 2
P3
2 1 1
2 2 2
P4
0 0 2
4 3 3
Allocation






Initially: Work = (3, 3, 2)
Step 1: Could use i=1 (Need=(1, 2, 2)) or i=3
(Need=0, 1, 1)). Choose i=3. Work=(5, 4, 3)
Step 2: Use i=1. Work=(7, 4, 3)
Step 3: Use i=0. Work=(7, 5, 3)
Step 4: Use i=4. Work=7, 5, 5)
Step 5: Use i=2. Work=(10, 5, 7) -----SAFE

Suppose P1 requests one resource of type A and 2 of type C.
If request > Available, the request must be denied. Otherwise,
simulate the granting of this request and check resulting state.
Granting this request would result in
Allocation
Max
Available
A B C
A B C
A B C
P0
0 1 0
7 5 3
2 3 0
P1
3 0 2
3 2 2
P2
3 0 2
9 0 2
P3
2 1 1
2 2 2
P4
0 0 2
4 3 3






Initially: Work = (2, 3, 0)
Step 1: Use i=1. Work=(5, 3, 2)
Step 2: Use i=3. Work=(7, 4, 3)
Step 3: Use i=4. Work=(7, 4, 5)
Step 4: Use i=0. Work=(7, 5, 5)
Step 5. Use i=2. Work=(10, 5, 7)-----SAFE.
Grant request.
What if original table looked like this?
Allocation
Max
Available
A B C
A B C
A B C
P0
0 1 2
6 4 3
1 2 2
P1
2 0 0
3 2 2
P2
3 1 0
7 4 6
P3
2 1 1
2 2 2
P4
0 0 2
4 3 3




Initially Work=(1, 2, 2)
Step 1: Process 1 Need = (1, 2, 2). Change Work to
(3, 2, 2)
Step 2: Process 3 Need = (0, 1, 1). Change Work to
(5, 3, 3)
Step 3. Process 4 Need = (4, 3, 1). Change Work to
(5, 3, 5). Process 0 Need = (6, 3, 1) and Process 2
Need = (4, 3, 6) ---- at this point, cannot continue --UNSAFE


RAG algorithm: does not generalize well but
more efficient.
Banker’s algorithm: generalizes better
(multiple resources of the same type) but less
efficient.


Deadlock Recovery:
Kill one of the processes – usually determined
by a priority.