91 lines
No EOL
2.5 KiB
Markdown
91 lines
No EOL
2.5 KiB
Markdown
### Monitors
|
|
Semaphores are hard to use in practice because quite low level Monitors provide an easier definition of concurrent objects at the level of Prog. Lang.
|
|
|
|
It guarantees mutual exclusion.
|
|
|
|
Inter-process synchronization is done through *conditions*, which are objects that provide the following operations:
|
|
- ***wait*:** the invoking process suspends, enters into the condition's queue, and releases the mutex on the monitor
|
|
- ***signal*:** if no process is in the condition's queue, the nothing happens. Otherwise
|
|
- reactivates the first suspended process, suspends the signaling process that however has a priority to re-enter the monitor (*Hoare semantics*)
|
|
- completes its task and the first process in the condition's queue has the priority to enter the monitor (after that the signaling one terminates or suspends) (*Mesa semantics*).
|
|
|
|
#### A very typical use: Rendez-vous
|
|
A soon as a process arrives at a barrier it needs to suspend and wait for every other process to reach the barrier.
|
|
|
|
```
|
|
monitor RNDV :=
|
|
cnt ∈ {0,…,m} init at 0
|
|
condition B
|
|
operation barrier() :=
|
|
cnt++
|
|
if cnt < m then
|
|
B.wait()
|
|
else
|
|
cnt <- 0
|
|
B.signal()
|
|
return
|
|
```
|
|
The last process wakes up one of the others, then he wakes up another one etc...
|
|
Of course, `signal()` will have no effect on the last process who calls it.
|
|
|
|
#### Monitor implementation through semaphores
|
|
*Hoare semantics*
|
|
|
|
- A semaphore MUTEX init at 1 (to guarantee mutex in the monitor)
|
|
- For every condition C, a semaphore SEMC init at 0 and an integer $N_{C}$ init at 0 (to store and count the number of suspended processes on the given condition)
|
|
- A semaphore PRIO init at 0 and an integer $N_{PR}$ init at 0 (to store and count the number of processes that have performed a signal, and so have priority to re-enter the monitor)
|
|
|
|
Every monitor operation starts with `MUTEX.down()` and ends with `if NPR > 0 then PRIO.up() else MUTEX.up()`
|
|
|
|
```
|
|
C.wait() :=
|
|
NC++
|
|
if NPR > 0 then
|
|
PRIO.up()
|
|
else
|
|
MUTEX.up()
|
|
SEMC.down()
|
|
NC--
|
|
return
|
|
|
|
C.signal() :=
|
|
if NC > 0 then
|
|
NPR++
|
|
SEMC.up()
|
|
PRIO.down()
|
|
NPR--
|
|
```
|
|
p.s. The wait **always** suspends, even if there is only a process.
|
|
|
|
#### Readers/Writers problem, strong priority to Readers
|
|
```
|
|
monitor RW_READERS :=
|
|
AR, WR, AW, WW init at 0
|
|
condition CR, CW
|
|
|
|
operation begin_read() :=
|
|
WR++
|
|
if AW != 0 then
|
|
CR.wait()
|
|
CR.signal()
|
|
AR++
|
|
WR--
|
|
|
|
operation end_read() :=
|
|
AR--
|
|
if AR + WR = 0 then
|
|
CW.signal()
|
|
|
|
operation begin_write() :=
|
|
if (AR+WR != 0 or AW != 0) then
|
|
CW.wait()
|
|
AW++
|
|
|
|
operation end_write() :=
|
|
AW--
|
|
if WR > 0 then
|
|
CR.signal()
|
|
else
|
|
CW.signal()
|
|
|
|
``` |