The Well-Grounded Java Developer

    Modern Java Concurrency
Are you a fluffy animal lover..?
         Leave now.



                              2
Why Modern Java Concurrency?
 • The WGJD wants to utilise modern hardware


 • The WGJD wants to write concurrent code
    - Safely
    - Without fear
    - With an understanding of performance implications


 • The WGJD wants to take advantage of:
    - JVM support for parallelised operations
    - An API that expands on synchronized


 • Modern Java Concurrency lets you do all of this
About this section
• We only have ~60mins hour to talk today


• Huge amount to talk about


• This subject typically fills 4 days worth of training


• We will give you some highlights today


• For die-hard low latency fiends
   - Locks are actually bad hmmkay!
   - Come talk to us afterwards to find out more
Modern Java concurrency
• Not a new subject
    - Underwent a revolution with Java 5
    - More refinements in 6 and 7
    - Another major library overhaul coming in 8 with lambdas


• java.util.concurrent (j.u.c) really fast in 6
    - Better yet in 7 & blazing in 8


• j.u.c. is still under-appreciated
    - Too much Java 4-style concurrency code still written
Java concurrency - Why not upgrade?
   • Too much legacy code?
      - People scared to refactor?


   • People don’t know j.u.c is easier?
      - People don’t know j.u.c is faster than classic?


   • People don’t know that you can mix-and-match
      - With a bit of care


   • Still not being taught at Universities?


   • Not enough people reading Doug Lea or Brian Goetz?
Perhaps... previous treatments
 didn't involve enough Otters.


     We will rectify this.

                             7
If you suffer from lutraphobia, you
      may want to leave now...


    Fluffy cute animals BITE

                               8
Otterly Amazing Tails of Modern Java
           Concurrency




   • Srsly
      - Otters! See those teeth? We warned you.
Why Otters?
• Otters are a very good metaphor
   - Not just because they look a bit
     like threads (i.e. long and thin)


• They are Collaborative,
 Competitive & Sneaky


• Hare off in opposite directions
   - Wreaking havoc if not contained
Otter Management (aka the 4 forces)
  • Safety
     - Does each object stay self-consistent?
     - No matter what other operations are happening?


  • Liveness
     - Does the program eventually progress?
     - Are any failures to progress temporary or permanent?


  • Performance
     - How well does the system take advantage of cores?


  • Reusability
     - How easy is it to reuse the system in other applications?
Some History
• Until recently, most CPUs had one processing core


• Multithreading was simulated on that single core
   - Not true concurrency


• Serial approach to algorithms often sufficed


• Interleaved multithreading can mask errors
   - Or be more forgiving than true concurrency


• Why, how and when did things change?
Moore’s Law
• “The number of transistors on an economic-to-
  produce chip roughly doubles every 2 years”


• Originally stated in 1965
   - Expected to hold for the 10 years to 1975
   - Still going strong


• Named for Gordon Moore (Intel founder)
   - About # transistors, not clock speed or overall performance
Transistor Counts
Transistor Counts
Moore’s Law - Problems
• Remember, it's not about overall performance


• Memory latency exponent gap
   - Need to keep the processing pipeline full
   - Add memory caches of faster SRAM “close” to the CPU
       • (L1, L2 etc)


• Code is restricted by L1 cache misses
   - Rather than CPU speed
   - After JIT compilation
Spending the transistor budget




• More and more complex contortions...
   - ILP, CMT, Branch prediction, etc, etc
Multi-core
• If we can’t increase clock speed / performance..
   - We have to go multi-core
   - Concurrency and performance are now tied together


• Real concurrency
   - Separate threads executing on cores at the same moment


• The JVM runtime controls thread scheduling
   - Java scheduling does NOT behave like OS scheduling


• Concurrency becomes the performance improver
Classic Java Concurrency
Classic Java Concurrency




• Why synchronized?


• Provides exclusion


• Need locking to make mutation concurrency-safe


• Locking gets complicated
   - Can become fragile
I wrap sychronized....
around entire classes


  Safe as Fort Knox
                         21
3 approaches to Concurrent Type Safety
    • Fully-synchronized Objects
       - Synchronize all methods on all classes


    • Immutability
       - Useful, but may have high copy-cost
       - Requires programmer discipline


    • Be Very, Very Careful
       - Difficult
       - Fragile
       - With Java - Often the only game in town
The JMM
• Mathematical description of memory


• Most impenetrable part of the Java language spec
   - Even worse than generics


• JMM makes minimum guarantees


• Real JVMs (and CPUs) may do more
   - Especially Intel chipsets
The JMM




• Primary concepts:
   -   synchronizes-with
   -   happens-before
   -   release-before-acquire
   -   as-if-serial
Synchronizes-with
Synchronizes-with
• Threads have their own desc of an object’s state
   - This must be flushed to main memory and other threads


• synchronized means that this local view:
   - Has been synchronized-with the other threads


• Defines touch-points where threads must perform
  synching
java.util.concurrent
java.util.concurrent

• Thanks, Doug Lea and co!


• j.u.c has building blocks for concurrent code
   -   ReentrantLock
   -   Condition
   -   ConcurrentHashMap
   -   CopyOnWriteArrayList
   -   Other Concurrent Data Structures
Locks in j.u.c




• Lock is an interface


• ReentrantLock is the usual implementation
Conditions in j.u.c
Conditions in j.u.c
HashMap




• HashMap has:
   - Hash function
   - Even distribution of buckets
ConcurrentHashMap (CHM)




• Concurrent form
   - Can lock independently
   - Seems lock-free to users
   - Has atomic operations
CopyOnWriteArrayList (COWAL)


•
CopyOnWriteArrayList (COWAL)
• Makes separate copies of underlying structure


• Iterator will never throw
 ConcurrentModificationException
CountDownLatch
CountDownLatch
• A group consensus construct


• countDown() decrements the count


• await() blocks until count == 0
   - i.e. consensus


• Constructor takes an int (the count)


• Quite a few use cases
   - e.g. Multithreaded testing
Example - CountDownLatch
Handoff Queue (in-mem)
Handoff Queue (in-mem)
• Efficient way to hand off work between threadpools


• BlockingQueue a good pick


• Has blocking ops with timeouts
   - e.g. for backoff / retry


• Two basic implementations
   - ArrayList and LinkedList backed


• Java 7 introduces the shiny new TransferQueue
Just use JMS!




                41
Example - LinkedBlockingQueue
Executors
Animals were harmed in the
 making of this presentation


    Crab got executed

                           44
Executors
• j.u.c execution constructs
   - Callable, Future, FutureTask


• In addition to the venerable
   - Thread and Runnable


• Stop using TimerTask!


• Executors class provides factory methods for
  making threadpools
   - ScheduledThreadPoolExecutor is one standard choice
Example - ThreadPoolManager
Example - QueueReaderTask
Fork/Join
Fork/Join
• Java 7 introduces F/J
   - similar to MapReduce
   - useful for a certain class of problems
   - F/J executions are not really threads


• In our example, we subclass RecursiveAction


• Need to provide a compute() method
   - And a way of merging results


• F/J provides an invokeAll() to hand off more tasks
Fork/Join




• Typical divide and conquer style problem
   - invokeall() performs the threadpool, worker & queue
     magic
Concurrent Java Code
• Mutable state (objects) protected by locks


• Concurrent data structures
   - CHM, COWAL


• Be careful of performance
   - especially COWAL


• Explicit synchronization for multi-threading


• Executor-based threadpools


• Queue-like handoffs used for asynch comms
Stepping Back
Stepping Back
• Concurrency is key to the future of performant code


• Mutable state is hard


• Need both synch & asynch state sharing


• Locks can be hard to use correctly


• JMM is a low-level, flexible model
   - Need higher-level concurrency model
   - Thread is still too low-level
Imagine a world...
• The JVM helped out the programmer more:
   -   Runtime-managed concurrency
   -   Collections were thread-safe by default
   -   Objects were immutable by default
   -   State was well encapsulated and not shared by default


• Thread wasn’t the default choice for unit of
  concurrent execution


• Copy-on-write was the basis for mutation of
  collections / synchronous multithreading


• Hand-off queues were the basis for asynchronous
  multithreading
What can we do with Java?
• We’re stuck with a lot of heritage in Java
   - But the JVM and JMM are very sound


• You don’t have to abandon Java
   - Mechanical sympathy and clean code get you far
   - The JIT compiler just gets better and better


• If we wanted to dream of a new language
   - It should be on the JVM
   - It should build on what we’ve learned in 15 years of Java
New Frontiers in Concurrency
• There are several options now on the JVM
   - New possibilities built-in to the language syntax
   - Synch and asynch models


• Scala offers an Actors model
   - And the powerful Akka framework


• Clojure is immutable by default
   - Has agents (like actors) & shared-nothing by default
   - Also has a Software Transactional Memory (STM) model


• Groovy has GPARs
Acknowledgments
• All Otter images Creative Commons or Fair Use


• Matt Raible
   - 20 criteria of selecting web frameworks


• Ola Bini
   - Polyglot pyramid


• Photos owned by Flickr Users
   - moff, spark, sodaro, lonecellotheory, tomsowerby
   - farnsworth, prince, marcus_jb1973, mliu92, Ed Zitron,
   - NaturalLight & monkeywing



• Dancing Otter by the amazing Nicola Slater @ folksy
Where is our beer!?




                      58
Thanks for listening! (@kittylyst,
          @karianna)

Modern Java Concurrency (OSCON 2012)

  • 1.
    The Well-Grounded JavaDeveloper Modern Java Concurrency
  • 2.
    Are you afluffy animal lover..? Leave now. 2
  • 3.
    Why Modern JavaConcurrency? • The WGJD wants to utilise modern hardware • The WGJD wants to write concurrent code - Safely - Without fear - With an understanding of performance implications • The WGJD wants to take advantage of: - JVM support for parallelised operations - An API that expands on synchronized • Modern Java Concurrency lets you do all of this
  • 4.
    About this section •We only have ~60mins hour to talk today • Huge amount to talk about • This subject typically fills 4 days worth of training • We will give you some highlights today • For die-hard low latency fiends - Locks are actually bad hmmkay! - Come talk to us afterwards to find out more
  • 5.
    Modern Java concurrency •Not a new subject - Underwent a revolution with Java 5 - More refinements in 6 and 7 - Another major library overhaul coming in 8 with lambdas • java.util.concurrent (j.u.c) really fast in 6 - Better yet in 7 & blazing in 8 • j.u.c. is still under-appreciated - Too much Java 4-style concurrency code still written
  • 6.
    Java concurrency -Why not upgrade? • Too much legacy code? - People scared to refactor? • People don’t know j.u.c is easier? - People don’t know j.u.c is faster than classic? • People don’t know that you can mix-and-match - With a bit of care • Still not being taught at Universities? • Not enough people reading Doug Lea or Brian Goetz?
  • 7.
    Perhaps... previous treatments didn't involve enough Otters. We will rectify this. 7
  • 8.
    If you sufferfrom lutraphobia, you may want to leave now... Fluffy cute animals BITE 8
  • 9.
    Otterly Amazing Tailsof Modern Java Concurrency • Srsly - Otters! See those teeth? We warned you.
  • 10.
    Why Otters? • Ottersare a very good metaphor - Not just because they look a bit like threads (i.e. long and thin) • They are Collaborative, Competitive & Sneaky • Hare off in opposite directions - Wreaking havoc if not contained
  • 11.
    Otter Management (akathe 4 forces) • Safety - Does each object stay self-consistent? - No matter what other operations are happening? • Liveness - Does the program eventually progress? - Are any failures to progress temporary or permanent? • Performance - How well does the system take advantage of cores? • Reusability - How easy is it to reuse the system in other applications?
  • 12.
    Some History • Untilrecently, most CPUs had one processing core • Multithreading was simulated on that single core - Not true concurrency • Serial approach to algorithms often sufficed • Interleaved multithreading can mask errors - Or be more forgiving than true concurrency • Why, how and when did things change?
  • 13.
    Moore’s Law • “Thenumber of transistors on an economic-to- produce chip roughly doubles every 2 years” • Originally stated in 1965 - Expected to hold for the 10 years to 1975 - Still going strong • Named for Gordon Moore (Intel founder) - About # transistors, not clock speed or overall performance
  • 14.
  • 15.
  • 16.
    Moore’s Law -Problems • Remember, it's not about overall performance • Memory latency exponent gap - Need to keep the processing pipeline full - Add memory caches of faster SRAM “close” to the CPU • (L1, L2 etc) • Code is restricted by L1 cache misses - Rather than CPU speed - After JIT compilation
  • 17.
    Spending the transistorbudget • More and more complex contortions... - ILP, CMT, Branch prediction, etc, etc
  • 18.
    Multi-core • If wecan’t increase clock speed / performance.. - We have to go multi-core - Concurrency and performance are now tied together • Real concurrency - Separate threads executing on cores at the same moment • The JVM runtime controls thread scheduling - Java scheduling does NOT behave like OS scheduling • Concurrency becomes the performance improver
  • 19.
  • 20.
    Classic Java Concurrency •Why synchronized? • Provides exclusion • Need locking to make mutation concurrency-safe • Locking gets complicated - Can become fragile
  • 21.
    I wrap sychronized.... aroundentire classes Safe as Fort Knox 21
  • 22.
    3 approaches toConcurrent Type Safety • Fully-synchronized Objects - Synchronize all methods on all classes • Immutability - Useful, but may have high copy-cost - Requires programmer discipline • Be Very, Very Careful - Difficult - Fragile - With Java - Often the only game in town
  • 23.
    The JMM • Mathematicaldescription of memory • Most impenetrable part of the Java language spec - Even worse than generics • JMM makes minimum guarantees • Real JVMs (and CPUs) may do more - Especially Intel chipsets
  • 24.
    The JMM • Primaryconcepts: - synchronizes-with - happens-before - release-before-acquire - as-if-serial
  • 25.
  • 26.
    Synchronizes-with • Threads havetheir own desc of an object’s state - This must be flushed to main memory and other threads • synchronized means that this local view: - Has been synchronized-with the other threads • Defines touch-points where threads must perform synching
  • 27.
  • 28.
    java.util.concurrent • Thanks, DougLea and co! • j.u.c has building blocks for concurrent code - ReentrantLock - Condition - ConcurrentHashMap - CopyOnWriteArrayList - Other Concurrent Data Structures
  • 29.
    Locks in j.u.c •Lock is an interface • ReentrantLock is the usual implementation
  • 30.
  • 31.
  • 32.
    HashMap • HashMap has: - Hash function - Even distribution of buckets
  • 33.
    ConcurrentHashMap (CHM) • Concurrentform - Can lock independently - Seems lock-free to users - Has atomic operations
  • 34.
  • 35.
    CopyOnWriteArrayList (COWAL) • Makesseparate copies of underlying structure • Iterator will never throw ConcurrentModificationException
  • 36.
  • 37.
    CountDownLatch • A groupconsensus construct • countDown() decrements the count • await() blocks until count == 0 - i.e. consensus • Constructor takes an int (the count) • Quite a few use cases - e.g. Multithreaded testing
  • 38.
  • 39.
  • 40.
    Handoff Queue (in-mem) •Efficient way to hand off work between threadpools • BlockingQueue a good pick • Has blocking ops with timeouts - e.g. for backoff / retry • Two basic implementations - ArrayList and LinkedList backed • Java 7 introduces the shiny new TransferQueue
  • 41.
  • 42.
  • 43.
  • 44.
    Animals were harmedin the making of this presentation Crab got executed 44
  • 45.
    Executors • j.u.c executionconstructs - Callable, Future, FutureTask • In addition to the venerable - Thread and Runnable • Stop using TimerTask! • Executors class provides factory methods for making threadpools - ScheduledThreadPoolExecutor is one standard choice
  • 46.
  • 47.
  • 48.
  • 49.
    Fork/Join • Java 7introduces F/J - similar to MapReduce - useful for a certain class of problems - F/J executions are not really threads • In our example, we subclass RecursiveAction • Need to provide a compute() method - And a way of merging results • F/J provides an invokeAll() to hand off more tasks
  • 50.
    Fork/Join • Typical divideand conquer style problem - invokeall() performs the threadpool, worker & queue magic
  • 51.
    Concurrent Java Code •Mutable state (objects) protected by locks • Concurrent data structures - CHM, COWAL • Be careful of performance - especially COWAL • Explicit synchronization for multi-threading • Executor-based threadpools • Queue-like handoffs used for asynch comms
  • 52.
  • 53.
    Stepping Back • Concurrencyis key to the future of performant code • Mutable state is hard • Need both synch & asynch state sharing • Locks can be hard to use correctly • JMM is a low-level, flexible model - Need higher-level concurrency model - Thread is still too low-level
  • 54.
    Imagine a world... •The JVM helped out the programmer more: - Runtime-managed concurrency - Collections were thread-safe by default - Objects were immutable by default - State was well encapsulated and not shared by default • Thread wasn’t the default choice for unit of concurrent execution • Copy-on-write was the basis for mutation of collections / synchronous multithreading • Hand-off queues were the basis for asynchronous multithreading
  • 55.
    What can wedo with Java? • We’re stuck with a lot of heritage in Java - But the JVM and JMM are very sound • You don’t have to abandon Java - Mechanical sympathy and clean code get you far - The JIT compiler just gets better and better • If we wanted to dream of a new language - It should be on the JVM - It should build on what we’ve learned in 15 years of Java
  • 56.
    New Frontiers inConcurrency • There are several options now on the JVM - New possibilities built-in to the language syntax - Synch and asynch models • Scala offers an Actors model - And the powerful Akka framework • Clojure is immutable by default - Has agents (like actors) & shared-nothing by default - Also has a Software Transactional Memory (STM) model • Groovy has GPARs
  • 57.
    Acknowledgments • All Otterimages Creative Commons or Fair Use • Matt Raible - 20 criteria of selecting web frameworks • Ola Bini - Polyglot pyramid • Photos owned by Flickr Users - moff, spark, sodaro, lonecellotheory, tomsowerby - farnsworth, prince, marcus_jb1973, mliu92, Ed Zitron, - NaturalLight & monkeywing • Dancing Otter by the amazing Nicola Slater @ folksy
  • 58.
    Where is ourbeer!? 58
  • 59.
    Thanks for listening!(@kittylyst, @karianna)

Editor's Notes

  • #2 TODO: If we have time replace code images with actual code\n
  • #3 Reference the ignite talk\n
  • #4 \n
  • #5 \n
  • #6 * Hands up for Java 6, 5, 4....\n* Hands up for j.u.c\n
  • #7 * Hands up if you’re daunted by the refactoring that would be required\n\n
  • #8 \n
  • #9 \n
  • #10 \n
  • #11 They are Apex Predators - think of them in that way\n
  • #12 The practice of managing your threads (or Otters!) is governed by four forces (after Doug Lea)\n
  • #13 \n
  • #14 \n
  • #15 \n
  • #16 It’s a little-known fact that Otters are scared of log-linear graphs\n
  • #17 * TODO: Need better wording for Code is restricted\n* Very successful within own frame of reference, but caveats\n* Reference Mechanical sympathy again here\n
  • #18 * So you can contort more and more, but you’re chasing diminishing returns\n* Ultimately, that exponent gap between clock speed and memory will do for you\n
  • #19 * Raise your hand if you use the process monitor on Ubuntu or another Linux. OK, have you seen how Java processes behave under that?\n
  • #20 \n
  • #21 * Explain that we’re going to show replacements for using synchronized\n* Raise your hand if you know why we use the keyword “synchronized” to denote a critical section in Java\n
  • #22 \n
  • #23 How performant do we think FS objects are?\nImmutability is good, but watch the copy-cost\n
  • #24 \n\n
  • #25 happens-before defines a “partial order” (if you’re a mathematician)\n\n
  • #26 \n
  • #27 * Hands up if you know what a (Non-Uniform Memory Access) NUMA architecture is?\n* In some ways, this is actually easier to explain on a NUMA arch...\n
  • #28 \n
  • #29 \n
  • #30 * Lock can in some cases directly replace synchronized, but is more flexible\n* MONITORENTER & MONITOREXIT\n* We use reentrant lock else recursive code deadlocks real quick\n
  • #31 TODO: Are we going to do the condition wait/notify sketch?\n
  • #32 Condition takes the place of wait() / notify() (Object monitors)\nTalk to the cases - 1 putter, 1 taker, many putters, few takers, few putters, many takers - think about this stuff at the design stage\n
  • #33 \n
  • #34 “What’s the worst thing that can happen if you’re iterating over the keys of a regular HashMap and someone alters it underneath you?”\n
  • #35 Basically it’s a drop-in replacement for regular HashMap\n
  • #36 \n
  • #37 Not quite a drop-in replacement - Performance needs to be thought about\nTODO Need to fix code sample so we have iterators\n
  • #38 \n
  • #39 \n
  • #40 \n
  • #41 \n\n
  • #42 BlockingQueue offers several different ways to interact with it (see the Javadoc)\n\n
  • #43 \n
  • #44 offer is similar to add but doesn’t throw exceptions\nProducers adding trade orders for example\nTODO Theatresports?\n
  • #45 Final building block for modern concurrent applications with Java\n
  • #46 \n
  • #47 \n
  • #48 * Let’s step through a quasi-realistic example\n* That cancel() code begs for some of that lambda treatment huh!\n
  • #49 \n
  • #50 \n\n
  • #51 As well as RecursiveAction there’s the more general ForkJoinTask\n\n
  • #52 Multithreaded Quicksort - shows a speedup from O(nlog n) to O(n) - not quite linear, but not bad\n
  • #53 So this is pretty much a statement of the state-of-the-art in Java concurrency\n
  • #54 \n
  • #55 * Thread is the assembly language of concurrency\n* We need to move to a more managed model\n
  • #56 \n
  • #57 * Coroutines, etc\nLMAX’s OSS “Disruptor” framework proves this\nAkka, Clojure etc\n
  • #58 \n
  • #59 \n
  • #60 \n
  • #61 \n