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 [Code One 2019]

This session continues the speaker’s investigation of concurrent programming in Java, with a strong emphasis on the implementation side. You’ll see how the JVM supports both the Java Concurrency API and the Java Memory Model. For example, you’ll learn 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 Memory Model imposes the restrictions it does. This is an update to the speaker’s 2016 session of the same name.

  • Be the first to comment

  • Be the first to like this

Java Concurrency, A(nother) Peek Under the Hood [Code One 2019]

  1. 1. 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, timing, and pricing of any features or functionality described for Oracle’s products may change and remains at the sole discretion of Oracle Corporation. Statements in this presentation relating to Oracle’s future plans, expectations, beliefs, intentions and prospects are “forward-looking statements” and are subject to material risks and uncertainties. A detailed discussion of these factors and other risks that affect our business is contained in Oracle’s Securities and Exchange Commission (SEC) filings, including our most recent reports on Form 10-K and Form 10-Q under the heading “Risk Factors.” These filings are available on the SEC’s website or on Oracle’s website at http://www.oracle.com/investor. All information in this presentation is current as of September 2019 and Oracle undertakes no duty to update any statement in light of new information or future events. Safe Harbor Copyright © 2019 Oracle and/or its affiliates.
  2. 2. Java Concurrency, A(nother) Peek Under the Hood [DEV4211] Principal Member of Technical Staff Java Platform Group September 19, 2019 David Buck Copyright © 2019 Oracle and/or its affiliates.
  3. 3. IoT Microservices DevOps in the Cloud Copyright © 2019 Oracle and/or its affiliates.
  4. 4. IoT Microservices DevOps in the Cloud Copyright © 2019 Oracle and/or its affiliates.
  5. 5. IoT Microservices DevOps in the Cloud Copyright © 2019 Oracle and/or its affiliates.
  6. 6. JVM Sustaining Engineer OpenJDK Update Project Maintainer JavaOne Rock Star Co-author of Oracle WebLogic Server 11g 構築・運用ガイド @DavidBuckJP https://blogs.oracle.com/buck/ Who am I? David Buck (left)
  7. 7. Program Agenda Introduction Background Tangent 1: Special Relativity History Implementation Tangent 2: HSDIS Future Conclusions 1 2 3 4 5 7 6
  8. 8. Introduction
  9. 9. Motivation “But I don’t write multithreaded code…”
  10. 10. 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/)]
  11. 11. GUI
  12. 12. 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)]
  13. 13. Batch Processing picture: US Social Security Administration (http://www.ssa.gov/history/acalcs.html) [Public domain]
  14. 14. “But I don’t write multithreaded code…”
  15. 15. “But I don’t write multithreaded code…”
  16. 16. 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/)]
  17. 17. 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)]
  18. 18. Observer Effect picture: Christian Schirm (Own work) [CC0]
  19. 19. Avoiding Heisenbugs Java Memory Model synchronized keyword java.util.concurrent
  20. 20. Avoiding Heisenbugs Java Memory Model synchronized keyword java.util.concurrent • Don’t do XXX • You must do YYY
  21. 21. a² + b² == c²
  22. 22. picture: WTF Public License, Version 2
  23. 23. Background
  24. 24. Memory Model
  25. 25. Memory Model Definition 1 Specification that explains when we can guarantee that a written value may be read correctly
  26. 26. void hogeMethod1() { int localA = 42; assert localA == 42; }
  27. 27. static int staticA; void hogeMethod2() { staticA = 42; assert staticA == 42; }
  28. 28. int data = 0; boolean ready = false; void hoge3() { while (!ready) {}; assert data == 42; } void hoge4() { data = 42; ready = true; }
  29. 29. Culprit #1
  30. 30. Culprit #2
  31. 31. Memory Ordering void hoge5() { a = 1; b = 2; c = 3; d = 4; e = 5; a = a + 1; }
  32. 32. 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; }
  33. 33. 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; }
  34. 34. Rule Single threaded behavior must never change
  35. 35. 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)]
  36. 36. 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
  37. 37. CPU Differences Loose Strict Alpha X86
  38. 38. CPU Differences Loose Strict
  39. 39. Memory Barriers int data = 0; boolean ready = false; void hoge3() { while (!ready) {}; assert data == 42; } void hoge4() { data = 42; ready = true; }
  40. 40. Memory Barriers int data = 0; boolean ready = false; void hoge3() { while (!ready) {}; assert data == 42; } void hoge4() { data = 42; ready = true; }
  41. 41. Memory Barriers int data = 0; boolean ready = false; void hoge3() { while (!ready) {}; assert data == 42; } void hoge4() { data = 42; ready = true; }
  42. 42. Memory Barriers Types store-store store-load load-store load-load
  43. 43. Compiler Barriers GCC __asm__ __volatile__("":::"memory"); VC++ _ReadBarrier _WriteBarrier _ReadWriteBarrier
  44. 44. Tangent 1: Special Relativity picture: Sakurambo (Own work) [Public domain]
  45. 45. Tangent 1: Special Relativity A B C
  46. 46. Tangent 1: Special Relativity A B C A, B, C
  47. 47. Tangent 1: Special Relativity A B C A, B, C C, B, A
  48. 48. Tangent 1: Special Relativity Observed order depends on viewer's frame of reference A B C A, B, C C, B, A
  49. 49. No single “correct” timeline Special Relativity Observed order of events depends on frame of reference
  50. 50. No single “correct” timeline Special Relativity Observed order of events depends on frame of reference Multithreaded Code Observed order of events depends on thread
  51. 51. Memory Model Definition 2 Clarify what multithreaded behavior developers may depend on
  52. 52. Memory Model Definition 2 Clarify what multithreaded behavior developers may depend on Limits what types of optimizations the runtime may do
  53. 53. History
  54. 54. 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)]
  55. 55. happened-before
  56. 56. Leslie Lamport LaTex happened-before picture: Leslie Lamport [GFDL (http://en.wikipedia.org/wiki/GFDL]
  57. 57. happened-before void hoge5() { a = 1; b = 2; c = 3; d = 4; e = 5; a = a + 1; }
  58. 58. happened-before void hoge4() { data = 42; ready = true; } void hoge3() { while (!ready) {}; assert data == 42; }
  59. 59. happened-before void hoge4() { data = 42; ready = true; } void hoge3() { while (!ready) {}; assert data == 42; }
  60. 60. 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
  61. 61. 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
  62. 62. JMM Specification
  63. 63. Original JMM Keywords synchronized mutual exclusion happened-before
  64. 64. Original JMM Keywords synchronized mutual exclusion happened-before volatile Visibility
  65. 65. Problems with the Original JMM volatile does not establish a happened-before relationship final values can change Many important runtime optimization were not allowed
  66. 66. Doug Lea Author of the Java Multithreaded bible Introduced his own OSS high- level multithreaded library
  67. 67. 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)]
  68. 68. Modern JMM JSR-133 Fixed shortcomings in original JMM volatile does establish happens-before final values will never change
  69. 69. Modern JMM Keywords synchronized mutual exclusion happened-before volatile visibility happened-before final immutability
  70. 70. 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;
  71. 71. volatile != atomic volatile int id = 0; int incID() { return id++; }
  72. 72. volatile != atomic volatile int id = 0; int incID() { return id++; } reg = [id] reg++ [id] = reg
  73. 73. volatile != atomic volatile int id = 0; synchronized int incID() { return id++; }
  74. 74. 64-bit updates are not guaranteed atomic • Reads and Writes to long and double values may not happen atomically • Possible to read a mix of two different writes Copyright © 2019 Oracle and/or its affiliates. Old value MSB New value LSB
  75. 75. 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
  76. 76. java.util.concurent JSR-166 Doug Lea’s OSS multithreading library
  77. 77. Multithreaded Control java.util.concurent synchronized wait()/notify() volatile / final Abstract Low-level
  78. 78. Fork/Join (JDK 7)
  79. 79. Functional Programming (JDK 8) Lambda Forms Stream API λ
  80. 80. Var Handles • Lower-level than volatile / final • Allows a value to be volatile only when we want it to be • Explicate fence and acquire / release semantics • Added in JDK 9 to replace several use cases previously only supported with sun.misc.Unsafe Copyright © 2019 Oracle and/or its affiliates.
  81. 81. Implementation
  82. 82. 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
  83. 83. Demos
  84. 84. ARM Assembly Crash Course
  85. 85. ARM Assembly Crash Course Op Target Source
  86. 86. ARM Assembly Crash Course MOV r02 #42
  87. 87. ARM Assembly Crash Course MOV r02 #42 r02 = 42
  88. 88. ARM Assembly Crash Course Op Target Source
  89. 89. ARM Assembly Crash Course Op Target Source Exception STR Source Target
  90. 90. ARM Assembly Crash Course MOV Copies registers MOV r02 r03 Writes Literals MOV r02 #42
  91. 91. ARM Assembly Crash Course LDx Loads data from memory to a register ldr r03, [r06] r03 = *r06
  92. 92. ARM Assembly Crash Course CMP / BEQ Compare and branch if equal cmp r0, #0 beq 0x74178d08 if (r0 == 0) goto 0x74178d08
  93. 93. ARM Assembly Crash Course DMB Data Memory Barrier dmb st dmb sy
  94. 94. One more thing…
  95. 95. Safe Points Methods proactively poll JVM makes page unreadable to stop the world movw ip, #45056 ; 0xb000 movt ip, #30461 ; 0x76fd ldr ip, [ip] ; {poll_return}
  96. 96. 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); } } }
  97. 97. Object Initialization public class ObjInit { static ObjInit globalRef = new ObjInit(); long number; public ObjInit() { number = 42; }
  98. 98. 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(); }}
  99. 99. 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
  100. 100. Future
  101. 101. JEP-188/JMM9 Not delivered with JDK 9 (JMM9 != JDK 9) JVM-level specification Compatibility with C11/C++11 Cover new features added since JDK 5 (e.g. AtomicX.weakCompareAndSet())
  102. 102. Conclusions
  103. 103. Avoid low-level API java.util.concurent synchronized wait()/notify() volatile / final Var handles Abstract Low-level
  104. 104. 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
  105. 105. Testing As close to production environment as possible Same hardware Same JRE (including version) Same settings
  106. 106. Testing As much variety as possible Various hardware Various JREs (including version) Various settings
  107. 107. Java Concurrency in Practice Java Concurrency Bible Covers JSR-133 / JSR-166
  108. 108. Summary Avoid low-level APIs Code against the standard, not the implementation Testing is always indispensible Must read Java Concurrency in Practice (JCiP)
  109. 109. Thank You!!!
  110. 110. [ JSR 133 (Java Memory Model) FAQ ] https://www.cs.umd.edu/~pugh/java/ memoryModel/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/cook book.html [ PrintAssembly ] https://wiki.openjdk.java.net/display/H otSpot/PrintAssembly [ BASIC DISASSEMBLER PLUGIN FOR HOTSPOT DOWNLOADS ] https://kenai.com/projects/base- hsdis/downloads References
  111. 111. Session Survey Help us make the content even better. Please complete the session survey in the Mobile App. Copyright © 2019 Oracle and/or its affiliates.
  112. 112. 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, timing, and pricing of any features or functionality described for Oracle’s products may change and remains at the sole discretion of Oracle Corporation. Statements in this presentation relating to Oracle’s future plans, expectations, beliefs, intentions and prospects are “forward-looking statements” and are subject to material risks and uncertainties. A detailed discussion of these factors and other risks that affect our business is contained in Oracle’s Securities and Exchange Commission (SEC) filings, including our most recent reports on Form 10-K and Form 10-Q under the heading “Risk Factors.” These filings are available on the SEC’s website or on Oracle’s website at http://www.oracle.com/investor. All information in this presentation is current as of September 2019 and Oracle undertakes no duty to update any statement in light of new information or future events. Safe Harbor Copyright © 2019 Oracle and/or its affiliates.

×