PV168

Memory Model


Memory Model

In computing, a memory model describes the interactions of threads through memory and their shared use of the data.[1]


Memory Model


Sequential Consistency

Compilers are allowed to reorder the instructions, when this does not affect the execution of the thread in isolation. [2]


Sequential Consistency

A = B = 0

// thread 1
r2 = A;
B = 1

// thread 2
r1 = B;
A = 2;

Synchronization Points


Actions


Shared variables


Happens-before


volatile


volatile

class VolatileExample {
    int x = 0;
    volatile boolean flag = false;
    public void writer() {
        x = 42;
        flag = true;
    }

    public void reader() {
        if (flag == true) {
          System.out.println(x); // guaranteed to see 42.
        }
    }
}

Atomic classes


Atomic classes

class AtomicExample {
    private int value = 0;
    private AtomicBoolean flag = new AtomicBoolean(false);
    public void writer() {
        value = 42;
        flag.set(true);
    }

    public void reader() {
        while (!flag.get()) {} // busy wait here
        System.out.println(value); // guaranteed to see 42.
    }
}

synchronized

public synchronized void doSomething() { /* ... */ }
public void doSomethingElse() {
    synchronized(this.attribute) {/* ... */}
}

Threads


Threads

class ThreadExample {
    public void run() {
        Integer value = 42;
        var t = new Thread(() -> value *= 2 );
        // value is 42
        t.start();
        t.join();
        // value is guaranteed to be 84;
    }
}

final Fields


final Fields


Double-Checked Locking

Is this correct?

class Foo {
    private Helper helper = null;
    public Helper getHelper() {
        if (helper == null) {
            synchronized(this) {
                if (helper == null)
                    helper = new Helper();
            }
        }
        return helper;
    }
}

Double-Checked Locking Fixed

Notice the volatile keyword.

class Foo {
    private volatile Helper helper = null;
    public Helper getHelper() {
        if (helper == null) {
            synchronized(this) {
                if (helper == null)
                    helper = new Helper();
            }
        }
        return helper;
    }
}

Double-Checked Locking Fixed 2

public class Foo {
  private Foo() {}

  private static class LazyHolder {
      static final Helper INSTANCE = new Helper();
  }

  public static Helper getHelper() {
      return LazyHolder.INSTANCE;
  }
}

How To Test The Correct Usage?


Without correct synchronization, very strange, confusing and counterintuitive behaviors are possible.

PV168

Course Summary


What have you experienced?


Programming is hard


Essential vs. Accidental Complexity


Naming things is hard


Structure matters


Interactions with PMs are tough


Functionality vs. Graphics


Duplicity is the Root of all Evil


Refactoring is hard


Team work is hard


Copy & Paste can be dangerous


Law of the Instrument

If the only tool you have is a hammer, it is tempting to treat everything as if it were a nail. (Abraham Maslow)


Source Code is Text


Thank you for your hard work!

You’ve learnt a lot about programming already.