$30 off During Our Annual Pro Sale. View Details »

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/
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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/
  7. 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() {} } }
  8. 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 } }
  9. 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
  10. 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
  11. 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
  12. 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
  13. 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
  14. 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
  15. 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; } }
  16. 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(); } }
  17. 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; } }
  18. 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)
  19. 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