SEAT = SEAT[0], // unreserved
SEAT[res: 0..1]
= ( query[res] -> SEAT[res]
| when (res==0) reserve -> SEAT[1] // now reserved
| when (res==1) reserve -> ERROR // error of being reserved twice
).
range S = 0..1
||SEATS = (seat[S]:SEAT).
At each terminal, a clerk can choose[s:S]
any of the
existing S seats and then makes a query on
whether it is reserved; is not reserved, they can then
reserve it. However, a double-booking from another terminal
must be avoided! This requires the clerk to acquire a lock
before the query on the seat and release it after either
reserving it or finding out it is already reserved.
SAVAGE = (getServing -> SAVAGE). COOK = (fillPot -> COOK).Model the behavior of the pot as an FSP process POT which would impose the respective constraints on the savage and cook processes.
sema = new Semaphore(v); // create new semaphore with value v (=0,1) sema.down(); // must wait if value is 0 sema.up(); // release other threads waiting on this semaphoreHint: have 2 semaphores, one to signify full the other to signify empty. Which one should be initially available (value=1)?
Now comment out synchronized(this) in both BufferSem methods, recompile, and re-run the program a few times? What do you observe now (and conclude)?
public synchronized void increment(int n) {
if (n > 0) {
value++;
increment(n-1);
}
}
If the object's associated lock was not recursive, a thread initially
entering the method (and hence acquiring the lock) would block on the
recursive call (when it has to re-acquire it).
(Ex 4.2 Magee & Kramer) Given the following declarations:
const N = 3 range P = 1..2 range C = 0..NModel a recursive lock as an FSP process RECURSIVE_LOCK which can support up to N levels of recursion for P possible threads. It will have the alphabet {acquire[p:P], release[p:P]} where acquire[p] represents thread p acquiring the lock.