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.
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 P i task body P i begin is loop
:
: wait critical section signal
:
: end loop end P i
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
process claims exclusive control of required resource.
Hold and Wait
process holds allocated resources while requesting more.
No preemption
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
Create an environment where deadlock is impossible.
Avoidance
Use algorithms to monitor resource allocation so that deadlock won’t happen.
Detection
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
Eliminate one of the previously mentioned necessary conditions, but which one?
Mutual Exclusion?
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:
R
P j i
P
R j i means resource R means process P j i is allocated to process P j is waiting for a resource of type R i
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.
P
1
P
2 P
3
R
3
R
1
R
2
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:
P
0
P
1
P
2
P
3
P
4
Allocation
A B C
0 1 0
2 0 0
3 0 2
2 1 1
0 0 2
Max
A B C
7 5 3
3 2 2
9 0 2
2 2 2
4 3 3
Available
A B C
3 3 2
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
Available
A B C
2 3 0 P
0
P
1
P
2
P
3
P
4
Allocation
A B C
0 1 0
3 0 2
3 0 2
2 1 1
0 0 2
Max
A B C
7 5 3
3 2 2
9 0 2
2 2 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.
P
0
P
1
P
2
P
3
P
4
Allocation Max Available
A B C
0 1 2
2 0 0
3 1 0
2 1 1
0 0 2
A B C
6 4 3
3 2 2
7 4 6
2 2 2
4 3 3
A B C
1 2 2
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.