Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Java Concurrency, A(nother) Peek Under the Hood [JavaOne 2016 CON1497]

169 views

Published on

A follow-up to my JavaOne 2015 “HotSpot Synchronization, a Peek Under the Hood” session, this year’s session continues the investigation of concurrent programming in Java, with a strong emphasis on the implementation side. You will see how the JVM supports both the Java concurrency API and the Java memory model. For example, the presentation looks at how Java language-level constructs such as the volatile keyword change the way the JVM accesses memory across a variety of CPUs. After this session, you should have a more intuitive sense of why the Java memory model imposes the restrictions that it does.

Published in: Software
  • Login to see the comments

Java Concurrency, A(nother) Peek Under the Hood [JavaOne 2016 CON1497]

  1. 1. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Java Concurrency A(nother) Peek Under the Hood David Buck Principal Member of Technical Staff Java SE Sustaining Engineering September, 2016
  2. 2. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Safe Harbor Statement The following is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle. 4
  3. 3. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | About Me David Buck • Java SE Sustaining Engineering • Mostly JRockit fixes • OpenJDK 8 Updates Project Maintainer • Hobbies: Programming
  4. 4. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Program Agenda Introduction Background Tangent 1: Special Relativity History Implementation Tangent 2: HSDIS Future Conclusions 1 2 3 4 5 6 6
  5. 5. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Introduction
  6. 6. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Motivation “But I don’t write multithreaded code…”
  7. 7. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Web Server picture: Coolcaesar at the English language Wikipedia [GFDL (http://www.gnu.org/copyleft/fdl.html) or CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0/)]
  8. 8. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | GUI
  9. 9. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Libraries picture: David Vignoni / ICON KING (http://icon-king.com) [LGPL (http://www.gnu.org/licenses/lgpl.html) or LGPL (http://www.gnu.org/licenses/lgpl.html)]
  10. 10. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Batch Processing picture: US Social Security Administration (http://www.ssa.gov/history/acalcs.html) [Public domain]
  11. 11. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | “But I don’t write multithreaded code…”
  12. 12. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | “But I don’t write multithreaded code…”
  13. 13. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Race Conditions picture: Sakurambo at English Wikipedia [GFDL (http://www.gnu.org/copyleft/fdl.html) or CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0/)]
  14. 14. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Heisenbugs Bug Heisenberg Heisenbug picture: Bundesarchiv, Bild 183-R57262 / Unknown / CC-BY-SA 3.0 [CC BY-SA 3.0 de (http://creativecommons.org/licenses/by-sa/3.0/de/deed.en)]
  15. 15. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Observer Effect picture: Christian Schirm (Own work) [CC0]
  16. 16. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Avoiding Heisenbugs • Java Memory Model • synchronized keyword • java.util.concurrent
  17. 17. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Avoiding Heisenbugs • Java Memory Model • synchronized keyword • java.util.concurrent • Don’t do XXX • You must do YYY
  18. 18. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | a² + b² == c²
  19. 19. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |picture: WTF Public License, Version 2
  20. 20. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Background
  21. 21. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Memory Model
  22. 22. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Memory Model Definition 1 Specification that explains when we can guarantee that a written value may be read correctly
  23. 23. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | void hogeMethod1() { int localA = 42; assert localA == 42; }
  24. 24. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | static int staticA; void hogeMethod2() { staticA = 42; assert staticA == 42; }
  25. 25. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | int data = 0; boolean ready = false; void hoge3() { while (!ready) {}; assert data == 42; } void hoge4() { data = 42; ready = true; }
  26. 26. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Culprit #1
  27. 27. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Culprit #2
  28. 28. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Memory Ordering void hoge5() { a = 1; b = 2; c = 3; d = 4; e = 5; a = a + 1; }
  29. 29. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Memory Ordering void hoge5() { a = 1; b = 2; c = 3; d = 4; e = 5; a = a + 1; } void hoge5() { a = 2; b = 2; c = 3; d = 4; e = 5; }
  30. 30. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Memory Ordering void hoge5() { a = 1; b = 2; c = 3; d = 4; e = 5; a = a + 1; } void hoge5() { b = 2; c = 3; d = 4; e = 5; a = 2; }
  31. 31. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Rule Single threaded behavior must never change
  32. 32. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Out of Order Execution picture: Amit6, original version (File:Superscalarpipeline.png) by User:Poil (Own work) [CC BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0)]
  33. 33. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | CPU Differences Type Alpha ARMv7 PA- RISC POWER SPARC RMO SPARC PSO SPARC TSO x86 x86 oostore AMD64 IA-64 zSeries load- load Y Y Y Y Y Y Y load- store Y Y Y Y Y Y Y store- store Y Y Y Y Y Y Y Y store- load Y Y Y Y Y Y Y Y Y Y Y Y Atomic (loads) Y Y Y Y Y Atomic (stores) Y Y Y Y Y Y Depend ent loads Y instruct ion cache Y Y Y Y Y Y Y Y Y Y chart source: https://en.wikipedia.org/wiki/Memory_ordering
  34. 34. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | CPU Differences Loose Strict Alpha X86
  35. 35. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | CPU Differences Loose Strict
  36. 36. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Memory Barriers int data = 0; boolean ready = false; void hoge3() { while (!ready) {}; assert data == 42; } void hoge4() { data = 42; ready = true; }
  37. 37. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Memory Barriers int data = 0; boolean ready = false; void hoge3() { while (!ready) {}; assert data == 42; } void hoge4() { data = 42; ready = true; }
  38. 38. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Memory Barriers int data = 0; boolean ready = false; void hoge3() { while (!ready) {}; assert data == 42; } void hoge4() { data = 42; ready = true; }
  39. 39. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Memory Barriers Types • store-store • store-load • load-store • load-load
  40. 40. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Compiler Barriers • GCC – __asm__ __volatile__("":::"memory"); • VC++ – _ReadBarrier – _WriteBarrier – _ReadWriteBarrier
  41. 41. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
  42. 42. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Tangent 1: Special Relativity picture: Sakurambo (Own work) [Public domain]
  43. 43. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Tangent 1: Special Relativity A B C
  44. 44. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Tangent 1: Special Relativity A B C A, B, C
  45. 45. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Tangent 1: Special Relativity A B C A, B, C C, B, A
  46. 46. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Tangent 1: Special Relativity Observed order depends on viewer's frame of reference A B C A, B, C C, B, A
  47. 47. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | No single “correct” timeline • Special Relativity – Observed order of events depends on frame of reference
  48. 48. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | No single “correct” timeline • Special Relativity – Observed order of events depends on frame of reference • Multithreaded Code – Observed order of events depends on thread
  49. 49. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Memory Model Definition 2 • Clarify what multithreaded behavior developers may depend on
  50. 50. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Memory Model Definition 2 • Clarify what multithreaded behavior developers may depend on • Limits what types of optimizations the runtime may do
  51. 51. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | History
  52. 52. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Java Memory Model (JMM) • Write once, run anywhere • 1995 • Part of the formal language specification • Happened-before picture: Peter Campbell [GFDL (http://www.gnu.org/copyleft/fdl.html) or CC BY-SA 4.0-3.0-2.5-2.0-1.0 (http://creativecommons.org/licenses/by-sa/4.0-3.0-2.5-2.0-1.0)]
  53. 53. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | happened-before
  54. 54. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Leslie Lamport • LaTex • happened-before picture: Leslie Lamport [GFDL (http://en.wikipedia.org/wiki/GFDL]
  55. 55. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | happened-before void hoge5() { a = 1; b = 2; c = 3; d = 4; e = 5; a = a + 1; }
  56. 56. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | happened-before void hoge4() { data = 42; ready = true; } void hoge3() { while (!ready) {}; assert data == 42; }
  57. 57. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | happened-before void hoge4() { data = 42; ready = true; } void hoge3() { while (!ready) {}; assert data == 42; }
  58. 58. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | happened-before void synchronized hoge4() { data = 42; ready = true; } void synchronized hoge3() { while (!ready) {}; assert data == 42; } Warning: if hoge3 is executed first, the above code will deadlock
  59. 59. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | happened-before void synchronized hoge4() { data = 42; ready = true; } void synchronized hoge3() { while (!ready) {}; assert data == 42; } Warning: if hoge3 is executed first, the above code will deadlock
  60. 60. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | JMM Specification
  61. 61. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Original JMM Keywords • synchronized – mutual exclusion – happened-before
  62. 62. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Original JMM Keywords • synchronized – mutual exclusion – happened-before • volatile – Visibility
  63. 63. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Problems with the Original JMM • volatile does not establish a happened-before relationship • final values can change • Many important runtime optimization were not allowed
  64. 64. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Doug Lea • Author of the Java Multithreaded bible • Introduced his own OSS high-level multithreaded library
  65. 65. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Java SE 5.0 • Modern JMM introduced • Lea’s library added to official JDK picture: Zvi Roger [CC BY 3.0 (http://creativecommons.org/licenses/by/3.0)]
  66. 66. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Modern JMM • JSR-133 • Fixed shortcomings in original JMM – volatile does establish happens-before – final values will never change
  67. 67. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Modern JMM Keywords • synchronized – mutual exclusion – happened-before • volatile – visibility – happened-before • final – immutability
  68. 68. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | JSR-133 の volatile void hoge4() { data = 42; ready = true; } void hoge3() { while (!ready) {}; assert data == 42; } Warning: if hoge3 is executed first, the above code will deadlock volatile boolean ready = false;
  69. 69. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | volatile != atomic volatile int id = 0; int incID() { return id++; }
  70. 70. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | volatile != atomic volatile int id = 0; int incID() { return id++; } reg = [id] reg++ [id] = reg
  71. 71. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | volatile != atomic volatile int id = 0; synchronized int incID() { return id++; }
  72. 72. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | happened-before • Monitor (acquisition / release) • Volatile (read / write) • final “freeze” (constructor) • JNI – System.out.println() – Input / Output • thread start()/join() • operations on j.u.concurrent collections
  73. 73. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | java.util.concurency • JSR-166 • Doug Lee’s OSS multithreading library
  74. 74. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Multithreaded Control • java.util.concurency • synchronized – wait()/notify() • volatile / final Abstract Low-level
  75. 75. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Fork/Join (JDK 7)
  76. 76. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Functional Programming (JDK 8) • Lambda Forms • Stream API λ
  77. 77. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Implementation
  78. 78. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Tangent 2: HSDIS (HotSpot Disassembler) • Lets us see code generated by JIT • Requires a disassembler plugin – GNU binutils-based plugin – base-hsdis • Command line options – +PrintAssembly – +CompileCommand=print,*MyClass.myMethod
  79. 79. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Demos
  80. 80. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | ARM Assembly Crash Course
  81. 81. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | ARM Assembly Crash Course Op Target Source
  82. 82. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | ARM Assembly Crash Course MOV r02 #42
  83. 83. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | ARM Assembly Crash Course MOV r02 #42 r02 = 42
  84. 84. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | ARM Assembly Crash Course Op Target Source
  85. 85. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | ARM Assembly Crash Course Op Target Source Exception STR Source Target
  86. 86. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | ARM Assembly Crash Course MOV Copies registers MOV r02 r03 Writes Literals MOV r02 #42
  87. 87. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | ARM Assembly Crash Course LDx Loads data from memory to a register ldr r03, [r06] r03 = *r06
  88. 88. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | ARM Assembly Crash Course CMP / BEQ Compare and branch if equal cmp r0, #0 beq 0x74178d08 if (r0 == 0) goto 0x74178d08
  89. 89. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | ARM Assembly Crash Course DMB Data Memory Barrier dmb st dmb sy
  90. 90. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | One more thing…
  91. 91. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Safe Points • Methods proactively poll • JVM makes page unreadable to stop world movw ip, #45056 ; 0xb000 movt ip, #30461 ; 0x76fd ldr ip, [ip] ; {poll_return}
  92. 92. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Long Value static long val = 0; public static void main(String[] args) { new Thread(() -> { while(true) val = -1L; } ).start(); new Thread(() -> { while(true) val = 0L; } ).start(); while (true) { long temp = val; if ( temp != -1 && temp != 0 ) { System.out.println("temp (DEC): " + temp); System.out.println("temp (BIN): " + Long.toBinaryString(temp)); System.exit(-1); } } } }
  93. 93. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Object Initialization public class ObjInit { static ObjInit globalRef = new ObjInit(); long number; public ObjInit() { number = 42; }
  94. 94. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Object Initialization public static void main(String[] args) { new Thread(() -> { while(true) { long temp = globalRef.number; if (temp != 42) { System.out.println(temp); System.exit(-1); } } } ).start(); new Thread(() -> { while(true) globalRef = new ObjInit(); } ).start(); }}
  95. 95. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | public class Loop extends Thread { static boolean done = false; public static void main(String[] args) { Thread childThread = new Loop(); childThread.start(); System.out.println("Starting loop"); spinWait(); System.out.println("Exited loop"); } private static void spinWait() { while (!done) ; } public void run() { try { Thread.sleep(5 * 1000); } catch (Exception e) {} done = true; } } // class Loop Loop
  96. 96. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Future
  97. 97. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | JEP-188/JMM9 • Not planned for JDK 9 (JMM9 != JDK 9) • JVM-level specification • Compatibility with C11/C++11 • Cover new features added since JDK 5 – (e.g. AtomicX.weakCompareAndSet())
  98. 98. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Conclusions
  99. 99. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Avoid low-level API • java.util.concurency • synchronized – wait()/notify() • volatile / final Abstract Low-level
  100. 100. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Code against the specification • Intermittent bugs are common • Behavior changes with JRE / platform • Stuff to avoid – synchronized (new Object()) { } – Randomly adding volatile declarations until it magically starts working
  101. 101. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Testing • As close to production environment as possible – Same hardware – Same JRE (including version) – Same settings
  102. 102. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Java Concurrency in Practice • Java Concurrency Bible • Covers JSR-133 / JSR-166
  103. 103. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Summary • Avoid low-level APIs • Code against the standard, not the implementation • Testing is always indispensible • Must read Java Concurrency in Practice (JCiP)
  104. 104. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Thank You!!!
  105. 105. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | • [ JSR 133 (Java Memory Model) FAQ ] https://www.cs.umd.edu/~pugh/java/memoryMo del/jsr-133-faq.html • [ Java Concurrency in Practice ] http://jcip.net/ • [ Concurrent Programming in Java ] http://gee.cs.oswego.edu/dl/cpj/ • [ The JSR-133 Cookbook for Compiler Writers ] http://gee.cs.oswego.edu/dl/jmm/cookbook.html • [ PrintAssembly ] https://wiki.openjdk.java.net/display/HotSpot/Pri ntAssembly • [ BASIC DISASSEMBLER PLUGIN FOR HOTSPOT DOWNLOADS ] https://kenai.com/projects/base- hsdis/downloads References
  106. 106. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Safe Harbor Statement The preceding is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle. 108
  107. 107. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 109

×