Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A practical approach to Java Memory Model

A practical approach to Java Memory Model

Java Memory Model is an interesting area of multi-thread programming. It describes how threads interact through memory and what behaviours are allowed in concurrent execution. Most of java developers are familiar with mutual exclusion and synchronized keyword but sometimes we forget that beside mutual exclusion we also have to care about memory visibility.

The talk will introduce number of examples to help understand JMM. It will use OpenJDK Java Concurrency Stress tests framework (JCStress) to validate the results.

Java2days Sofia 2017
Devoxx UK 2018 https://www.youtube.com/watch?v=pS5dPQwgnYo
JBCNConf Barcelona 2018

https://github.com/amczarny/JMMPresentation

amczarny

May 11, 2018
Tweet

More Decks by amczarny

Other Decks in Programming

Transcript

  1. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    A practical approach to Java Memory Model
    A practical approach to Java Memory Model
    Andrzej Czarny
    https://www.ocadotechnology.com/

    View full-size slide

  2. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Ocado Technology
    Senior Software Engineer - Simulation Algorithm Development

    View full-size slide

  3. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Contents
    • Out of order execution
    • Introduction to JCStress
    • Basic JMM concepts and definitions
    • Examples/Puzzles
    • Future of JMM

    View full-size slide

  4. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Out of order execution
    • Compiler optimizations
    • Hardware CPU cache optimization

    View full-size slide

  5. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    public class JITOptimization {
    private static boolean flag = true;
    public static void main(String ... args) throws InterruptedException {
    new Thread(JITOptimization::loop).start();
    Thread.sleep(1000);
    new Thread(JITOptimization::terminate).start();
    }
    public static void terminate() {
    flag = false;
    System.out.println("Flag has been changed");
    }
    public static void loop() {
    boolean printOnce = true;
    while (getFlag()) {
    if (printOnce) {
    printOnce = false;
    System.out.println("I'm in the loop");
    }
    }
    System.out.println("I'm outside of the loop");
    }
    public static boolean getFlag() { return flag;}
    }
    JIT optimization

    View full-size slide

  6. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    public class JITOptimization {
    private static boolean flag = true;
    public static void main(String ... args) throws InterruptedException {
    new Thread(JITOptimization::loop).start();
    Thread.sleep(1000);
    new Thread(JITOptimization::terminate).start();
    }
    public static void terminate() {
    flag = false;
    System.out.println("Flag has been changed");
    }
    public static void loop() {
    boolean flag = getFlag();
    while (flag) {
    }
    }
    public static boolean getFlag() { return flag;}
    }
    JIT optimization

    View full-size slide

  7. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Demo 1

    View full-size slide

  8. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Processor
    Symmetric multiprocessing
    Memory
    C-1 C-2 C-3 C-4 C-5
    Thread
    2
    C-0
    Thread
    1

    View full-size slide

  9. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Processor
    OutOfOrder execution
    C-0
    Execution Engine
    Store
    Buffer
    L1
    L2
    L3
    C-5
    L S
    Load
    Buffer
    Memory
    r2 = x
    y:524
    Coherence
    Protocol
    x = 168 store
    r1 = y load

    View full-size slide

  10. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Processor
    OutOfOrder execution
    C-0
    Execution Engine
    Store
    Buffer
    L1
    L2
    L3
    C-5
    L S
    Load
    Buffer
    Memory
    r2 = x
    y:524
    x = 168 store
    r1 = y load
    Coherence
    Protocol
    168

    View full-size slide

  11. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Processor
    OutOfOrder execution
    C-0
    Execution Engine
    Store
    Buffer
    L1
    L2
    L3
    C-5
    L S
    Load
    Buffer
    Memory
    r2 = x
    x = 168 store
    r1 = y load
    Coherence
    Protocol
    168 168
    168

    View full-size slide

  12. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Hardware CPU cache optimization
    Type Alpha ARMv7 POWER SPARC x86
    LoadsLoads mb dmb lwsync
    LoadsStores mb dmb hwsync
    StoresStores wmb dmb-st lwsync
    StoresLoads mb dmb hwsync membar
    mfence
    locked
    insn
    Weak memory model Strong memory model

    View full-size slide

  13. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    JCStress Tutorial
    The Java Concurrency Stress tests (jcstress) is an experimental harness and a suite of
    tests to aid the research in the correctness of concurrency support in the JVM, class
    libraries, and hardware.
    http://openjdk.java.net/projects/code-tools/jcstress/

    View full-size slide

  14. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Test Example
    public class SomeTest {
    @JCStressTest
    @State
    @Outcome(id="1", expect=Expect.ACCEPTABLE_INTERESTING, desc="special case")
    public static class Test1 {
    @Actor public void actor1(II_Result r) {}
    @Arbiter public void arbiter(II_Result r) {}
    }
    @JCStressTest(Mode.Termination)
    @State
    public static class Test2 {
    @Actor public void actor1(II_Result r) {}
    @Signal public void signal() {}
    }
    }

    View full-size slide

  15. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    StoreLoad reordering
    @JCStressTest @State
    public class StoreLoad {
    int x, y;
    @Actor public void actor1(II_Result r) {
    x = 1; //store
    r.r1 = y; //load
    }
    @Actor public void actor2(II_Result r) {
    y = 1; //store
    r.r2 = x; // load
    }
    }

    View full-size slide

  16. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Demo 2

    View full-size slide

  17. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    “The Java Memory Model was the first attempt to provide a
    comprehensive threading memory model for a popular
    programming language.”
    https://en.wikipedia.org/wiki/Memory_model_(programming)
    Java Memory Model

    View full-size slide

  18. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    JMM history
    • Before JSR133
    – Not possible to create thread-safe immutable objects
    – Reordering volatile and non volatile fields
    • JSR133
    – Java 1.5
    – Thread-safe immutable object
    – More powerful volatile

    View full-size slide

  19. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Synchronized-with relations
    unlock action on monitor x
    write to a volatile variable x
    action that starts a thread
    final action in a thread
    all subsequent lock actions on x
    all subsequent reads of x
    first action in a thread
    any action that detects
    that a thread has terminated
    Thread A Thread B

    View full-size slide

  20. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Happens-before Order
    Thread A
    Operation 1
    Operation 2
    Operation 3
    synchronized(y)
    Operation 4
    Thread B
    Operation
    write volatile z
    Operation 2
    read volatile x
    synchronized(v)
    write volatile x
    Operation 3
    Operation 4
    Operation 5

    View full-size slide

  21. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Happens-before Order
    Order for
    Thread B
    Operation 1, 2 results
    Operation 1
    write volatile z
    Operation 2
    read volatile x
    synchronized(v)
    Operation 3
    write volatile x
    Thread A
    Operation 1
    Operation 2
    Operation 3
    synchronized(y)
    Operation 4
    Thread B
    Operation 1
    write volatile z
    Operation 2
    read volatile x
    synchronized(v)
    write volatile x
    Operation 3
    Operation 4
    Operation 5
    Operation 4

    View full-size slide

  22. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Happens-before Order
    Order for
    Thread B
    Operation 1
    write volatile z
    Operation 2
    read volatile x
    synchronized(v)
    Operation 3
    write volatile x
    Thread A
    Operation 1
    Operation 2
    Operation 3
    synchronized(y)
    Operation 4
    Thread B
    Operation 1
    write volatile z
    Operation 2
    read volatile x
    synchronized(v)
    write volatile x
    Operation 3
    Operation 4
    Operation 5
    Operation 4

    View full-size slide

  23. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    final Fields Semantics

    View full-size slide

  24. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Thread-safe immutable object
    @JCStressTest @State
    public class AmIImmutable {
    static AmIImmutable i = new AmIImmutable();
    int x, y, z;
    AmIImmutable() {
    x = 1;
    y = 2;
    z = 3;
    }
    @Actor public void actor1() {
    i = new AmIImmutable();
    }
    @Actor public void actor2(III_Result r) {
    AmIImmutable tmp = i;
    r.r1 = tmp.x;
    r.r2 = tmp.y;
    r.r3 = tmp.z;
    }
    }

    View full-size slide

  25. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Demo 3

    View full-size slide

  26. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Thread-safe immutable object
    @JCStressTest @State
    public class Escape {
    volatile static IntSupplier supplier;
    static Escape escape = new Escape();
    final int x;
    public Escape() {
    supplier = () -> getX();
    x = 1;
    }
    int getX(){return x;}
    @Actor public void actor1() { escape = new Escape(); }
    @Actor public void actor2(II_Result r) {
    r.r1 = supplier.getAsInt();
    r.r2 = escape.getX();
    }
    }

    View full-size slide

  27. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Demo 4

    View full-size slide

  28. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    volatile

    View full-size slide

  29. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Thread-safe immutable object
    @JCStressTest @State
    public class AmISynchronized {
    int y = 1;
    volatile int x = 1;
    @Actor public void actor1() {
    y = 2;
    x = 3;
    }
    @Actor public void actor2(I_Result r) {
    r.r1 = y * x;
    }
    }

    View full-size slide

  30. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Demo 5

    View full-size slide

  31. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    What next
    • JEP 188: Java Memory Model Update
    – Improve formalization
    – JVM coverage
    – Extend scope (AtomicX.weakCompareAndSet)
    – C11/C++11 compatibility
    – Implementation guidance. JVM implementors
    – Testing support
    – Tool support (static analysis)

    View full-size slide

  32. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Summary
    Never ignore concurrency issues!
    Use highest level of abstraction
    Check framework requirements regarding concurrency
    Code against specification not implementation
    Always use final on immutable classes

    View full-size slide

  33. https://github.com/amczarny/JMMPresentation
    https://github.com/amczarny/JMMPresentation
    Q & A

    View full-size slide