Task Graphs

Mit wie vielen Prozessoren ist minimal

Check: wenn critical-path time < time mit split up noch nicht ideal split gefunden!

  • weil Critical-Path length = length mit unendlich prozessoren.

Wait/Notify

Supervisor der Interrupted (FS21)

thread.interrupt() called den interrupt. Mit thread.join() kann man dann warten bis sie fertig sind.
Check das extends Thread gegeben ist.

Too much Synchronization

Be careful to only synchronise the sections where it’s necessary!
I.e. the synchro block only around the statements that need waiting, etc…

Fork/Join

Im Fork/Join Framework wird

  • RecursiveTask<Double> verwendet um einen Wert zurückzugeben.
  • RecursiveAction verwendet, wenn in-place alles geschieht

Internals

Both ForkJoin and Executor coordinate Tasks Threads, keep a list of running threads that are assigned work

ForkJoin internal Queue + Work Stealing

Speedup

Exponential Speedup

We define exponential speedup as .

Locks

see definitions.

State Space Diagram

The modifications on a line of code only kick in after we’ve moved to the next state.

  • so victim[me] = true is only visible when in the line after.

deadlock-free: no outgoing edges on a state
livelock: cycle with no CS
mutex: no state with both in CS

Filter Lock

It’s not Fair, since it doesn’t have a FCFS guarantee.
It only guarantees that the lastToEnter the section does not leave. If there is more than 1 Thread waiting, they can skip each other through wake-up order.

Linearizability

Atomic Registers

Atomic Registers

Atomic Registers = linearizable SC

synchronized and linearisability

A synchronized method does not guarantee the existance of a linearisation point, in two exception cases:

Mixed Access

if we access the same objects in the synchronized method, but not all accesses are synchronized, we get issues (lost writes, etc…)

Real-time order

​ iff the response of ​ precedes the invocation of in . This is a partial order: concurrent calls are unordered.

Example A:

class Account {
    private int balance = 100;
    public synchronized void deposit(int x) { balance += x; }
    public void withdraw(int x) { balance -= x; } // forgot synchronized
    public synchronized int get() { return balance; }
}

Two threads, one deposits and one withdraws, with the withdraw overwriting the extra balance added through the lost write (in the end it’s 90).
A third thread reads at the end, after all calls complete.

Real time order forces:

  • thread 1: deposit get
  • thread 2: deposit get
    so get is always last. the specification demands the balance to be 100 in the end.

We cannot find a single linearisation point where balance goes from 100 110 (the linearisation point for withdraw).

We can also observe failures with the JMM:
Example B (Java)

class Flag {
    private boolean done = false;
    public synchronized void finish() { done = true; }
    public boolean isDone() { return done; }             // unsynchronized
}

Even though finish() returns, we can still observe isDone > false because SAs only apply to things that use the same monitor.

  • order only applies to things using the same monitor.

The unsynchronized access can still legally ignore the update.

Wait

Wait does not always prevent linearisability, but without the while (retry) it does:

public synchronized void put(T v) throws InterruptedException {
    if (count == buf.length) wait();                 // BUG
    buf[tail] = v; tail = (tail + 1) % buf.length; count++;
    notifyAll();
}

Buffer full, assume we have two producers notifyAll by a consumer wakes both up.

  • Since no while check, they both try to remove one and nether rechecks.

If the while was there, the second thread would have checked for full again before trying.

Consensus

State Proofs

Univalent

State who’s children all make the same decision.

Bivalent

State where children can still be both 0 or 1.

Critical State

A protocol state is critical if:

  • it is bivalent
  • if any thread moves, the protocol state becomes univalent (The art of multiprocessor programming p106)