73 lines
3.3 KiB
Markdown
73 lines
3.3 KiB
Markdown
Critical sections (locks) have drawbacks:
|
|
- if not put at the right level of granularity, they unnecessarily reduce concurrency
|
|
- delays of one process may affect the whole system
|
|
|
|
**MUTEX-freedom:** the only atomicity is the one provided by the primitives themselves (no wrapping of code into CSs)
|
|
the liveness properties used so far cannot be used anymore, since they rely on CSs.
|
|
(example: if we have only atomic R/W registers, these are the only atomic things that we have. But we may also have atomic primitives like *test&set*, *compare&swap* ecc.).
|
|
|
|
#### Liveness properties
|
|
We have four new liveness properties
|
|
1. **Obstruction freedom:** every time an operation is run in isolation (no overlap with any other operation on the same object), it terminates
|
|
2. **Non-blocking:** whenever an operation is invoked on an object, eventually one operation on that object terminates
|
|
- reminds deadlock-freedom in MUTEX-based concurrency
|
|
3. **Wait freedom:** whenever an operation is invoked on an object, it eventually terminates
|
|
- reminds starvation-freedom in MUTEX-based concurrency
|
|
4. **Bounded wait freedom:** wait freedom + a bound on the number of steps needed to terminate
|
|
- reminds bounded bypass in MUTEX-based concurrency
|
|
|
|
*REMARK:* these notions naturally cope with (crash) failures. Fail stop is another way of terminating, there is no way of distinguishing a failure from an arbitrary long sleep (because of asynchrony).
|
|
|
|
### A wait-free Splitter
|
|
Assume we have atomic R/W registers.
|
|
|
|
A **splitter** is a concurrent object that provides a single operation **dir** such that:
|
|
1. (*validity*) it returns L, R or S (left, right, stop)
|
|
2. (*concurrency*) in case of n simultaneous invocations of **dir**
|
|
1. at most n-1 L are returned
|
|
2. at most n-1 R are returned
|
|
3. at most 1 S is returned
|
|
3. (*wait freedom*) it eventually terminates.
|
|
|
|
Idea:
|
|
- not all processes obtain the same value
|
|
- in a solo execution (i.e., without concurrency) the invoking process must stop (0 L && 0 R && at most 1 S)
|
|
|
|
We have:
|
|
- DOOR: MRMW boolean atomic register initialized at 1
|
|
- LAST: MRMW atomic register initialized at whatever process index
|
|
|
|
```
|
|
dir(i) :=
|
|
LAST <- i
|
|
if DOOR = 0 then
|
|
return R
|
|
else
|
|
DOOR <- 0
|
|
if LAST = i then
|
|
return S
|
|
else
|
|
return L
|
|
```
|
|
With 2 processes, we can have:
|
|
- one goes left and one goes right
|
|
- one goes left and the other stops
|
|
- one goes right and the other stops
|
|
|
|
#### Soundness theorem
|
|
this implementation satisfies the three requirements for the splitter
|
|
|
|
*Proof:*
|
|
1. Not all processes can obtain R
|
|
- the door must have been closed and who closed the door cannot obtain R
|
|
2. not all processes can obtain L
|
|
- let us consider the last process that writes into LAST (this is an atomic register, so this is meaningful)
|
|
- if the door is closed, it receives R and √
|
|
3. let $p_i$ be the first process that receives $S \to LAST=i$ in its second if
|
|
![[Pasted image 20250324091452.png]]
|
|
|
|
### An Obstruction-free Timestamp Generator
|
|
A **timestamp generator** is a concurrent object that provides a single operation get_ts such that:
|
|
1. (*validity*) not two invocations of get_ts return the same value
|
|
2. (*consistency*) if one process terminates its invocation of get_ts before another one starts, the first receives a timestamp that is smaller than the one received by the second one
|
|
3. (*obstruction freedom*) if run in isolation
|