Speedup, Gustafson’s, Amdahl’s
2.
Lower bound für wieviele Prozessoren gebraucht werden: “hat die Maschine mindestens!
. Dann gilt .
Nicht auf das vergessen.
3.
Für mit , gilt dass bounded ist!
as .
Pipelining
b)
Angenommen Pipeline leer, wie lange bis 100 Bilder durch sind.
Formel: latency (first element) + max(stage_time) * (n - 1).
Also in unserem Fall .
Threads
Synchronized needed
We cannot call
wait()ornotifyon the class’s Monitor without having the methodsynchronized.
Synchronized is very necessary here!
Wait/Notify
Do not forget the synchronized around the while (true) inner block!
Without it again, we cannot call wait().
The general pattern here is:
- while (true) for consumer (post office)
- set current = null
- increment current ticketnum
- notifyAll
- busywait until consumer is not null
- serve consumer
the consumer should also be synchronized and wait() with a while until it’s his turn, when he sets customer == this.
Do not forget synchronized(this) { ... } block!
Fork/Join
You need:
new Task(...)- then
.compute()or.fork()- then
.join()for the forked task
- then
- finally recombine elements
- make sure boundary cases are handled:
- going over middle sep
- combining left/right into one
- make sure boundary cases are handled:
For the correct splitting:
int mid = length / 2;
Task left = new Task(array, start, mid); // this is exclusive mid
Task right = new Task(array, start+mid, length - mid); // inclusive mid hereMake sure to correctly initialise Sequence → no length, initial len is 1, only using extend!
3)
We can of course split the work into 3 different segments and recombine (if easily splittable by 3) → just as efficient.
ForkJoinPool in which RecursiveTask is executed is just special ExecutorService and can handle an arbitrary amount of threads.
State Diagrams
b)
- Deadlock
- only if a state has no outgoing edges is possible
- Livelock
- only if there is a cycle in which both threads make no progress
- i.e. without entering the critical section
- “no cycle without having both threads enter the critical section”
- only if there is a cycle in which both threads make no progress
- Mutex
- No state every reaches
[CS, CS, -]
- No state every reaches
- Wait-Free
- wait-free = non-blocking + everyone makes progress
- only if failure or suspension of one thread cannot cause failure or suspension of another thread
→ here one thread being blocked means state never switches back to next == 1/0 and thus the other is also blocked.
Synchronization
9)
Mutex for can be implemented with:
- atomic registers (filter lock, bakery lock)
- locks
- CAS
- STM (only guarantees atomicity, but aborts everyone but one → optimistic concurrency control)
Wait-free consensus for ;
- atomic-registers → NO
- locks → NO
- CAS → YES
ABA problem occurs for:
- atomic registers
- CAS
not for Locks or STM (because of global clock and timestamps)
10)
private int factor = 1;
private final AtomicBoolean full = new AtomicBoolean(false);
public void Update1(int multiplier) {
while (!full.compareAndSet(false, true));
factor *= multiplier; // CS
full.set(false);
}Lock-free? NO → uses Spinlock here.
- For lock-freedom it would have to be
- non-blocking → it blocks on CAS
- someone makes progress
- if one thread dies in the CS, all are blocked!
Mutex for 2 or threads → YES
private final AtomicInteger factor = new AtomicInteger(1);
boolean Update2(float multiplier, int retries) {
while (retries >= 0) {
int val = factor.get();
int res = val * multiplier;
if (factor.compareAndSet(val, res)) {
return true;
}
--retries;
}
return false;
}This code uses optimistic concurrency control.
Optimistic concurrency control
First fetching element, then doing some work on it and finally checking if the element was not modified before writing-back (atomically.
If the element was modified, restart.
Linearizability
a)
- Linearizability ⇒ Sequential consistency
sequential consistency means it’s a legal history if we allow reordering threads arbitrarily, no matter what, just inter-thread PO has to be respected.
Linearizability demands that we cannot reorder non-overlapping sections!
- Sequential ⇒ Linearizable
- FALSE, sequential is weaker
Sequential vs. linearizable counterexample 15.2.1 Comparing SC and Linearizability
-
sequential History is legal, if every teilhistorie is legal
- TRUE, by def.
- legal sequential history: for every , is legal sequential history.
- TRUE, by def.
-
Komplette historie immer linearisierbar
- FALSE
- komplette historie = no pending invocations
-
Zwei historien equivalent wenn beide linearisierbar sind
- FALSE
- H, G equivalent wenn for all threads = .
b)
- H1 und H2 können nicht vom selben Programm erzeugt worden sein
- FALSE
- histories are equivalent for each thread (projections) as the calls match exactly, just the inter-thread order is different
- H1 is linearisable
- false, we can check from the diagrams

History → Diagram
We can create the diagram from the history by drawing a line between matching invocations, i.e.
q.w(2) -> q:void, etc…
- H2 is a sequential history
- FALSE, sequential only when threads don’t interleave.
- final pending invocation is ok
- FALSE, sequential only when threads don’t interleave.
Barriers and Synchronisation
a)
Inefficient: yes, busy waiting (not spinlock!) is inefficient.
b)
Within a synchronized, the even non-atomic statements like i++ are of course atomic. Thus it completes perfectly fine.
c)
Implement a barrier for any number of threads, that other threads can already enter while the rest are exiting.
Intuition:
- Hold threads while the barrier is draining, use a spinlock or wait()
- Count up, then down
- when all are out, allow the next ones to proceed through.
public class Barrier {
final int threads;
private int i = 0;
private boolean holding = false;
public void synchronized await(){
while(holding){
wait();
}
i++;
while(i < n && !holding){
wait();
}
if(i==n){
holding = true;
notifyAll();
}
i--;
if(i==0){
holding = false;
notifyAll();
}
}
}Why no volatile? Having everything inside the synchronized block gives us the same properties as the volatile does. → unlocking/locking monitor is also a synchronization action.
Semaphores
a) Multi-Semaphore
Java-Monitore = java object monitors, just use synchronized.
synchronized void acquire(int n) {
while (n > count)
wait();
count -= n;
}
synchronized void release(int k) {
count += k;
notifyAll();
}b)
just set the multisemaphore to and then acquire 1 or 3 depending on either car or truck.