Concurrency on the JVM

3,450 views

Published on

Published in: Technology
0 Comments
11 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,450
On SlideShare
0
From Embeds
0
Number of Embeds
26
Actions
Shares
0
Downloads
118
Comments
0
Likes
11
Embeds 0
No embeds

No notes for slide

Concurrency on the JVM

  1. 1. <ul>Concurrency </ul><ul>Unleash your processor(s) Václav Pech </ul>
  2. 2. <ul>About me </ul><ul><li>Passionate programmer
  3. 3. Concurrency enthusiast
  4. 4. GPars @ Codehaus lead
  5. 5. Technology evangelist @ JetBrains
  6. 6. JetBrains Academy member </li></ul><ul>http://www.jroller.com/vaclav </ul><ul><ul><li>http://twitter.com/vaclav_pech </li></ul></ul>
  7. 7. <ul>The evil accumulator </ul><ul><li>int sum=0;
  8. 8. for(int i : collection) sum += i; </li></ul>
  9. 9. <ul>We’re quad core already </ul><ul>Beware: More cores to come shortly! </ul>
  10. 10. <ul>Stone age of parallel SW </ul><ul><li>Dead-locks
  11. 11. Live-locks
  12. 12. Race conditions
  13. 13. Starvation
  14. 14. Shared Mutable State </li></ul>
  15. 15. <ul>Lock and synchronize </ul><ul>Multithreaded programs today work mostly by accident! </ul>
  16. 16. <ul>Can we do better? </ul><ul>Map/Reduce </ul><ul>Fork/Join </ul><ul>Actors </ul><ul>STM </ul><ul>Dataflow </ul><ul>Agent </ul>
  17. 17. <ul>Asynchronous invocation </ul><ul>Future f = threadPool.submit (calculation); … System.out.println( “Result: “ + f.get()); </ul><ul>main </ul><ul>calculation </ul><ul>get() </ul>
  18. 18. <ul>Collections (GPars) </ul><ul>images. eachParallel {it.process()} documents. sumParallel () candidates. maxParallel {it.salary}.marry() </ul>
  19. 19. <ul>Parallel Arrays (jsr-166y) </ul><ul>ParallelArray namesOfWomen = people .withFilter( aWoman ).withMapping( retrieveName ).all(); Ops.Predicate aWoman = new Ops.Predicate() { public boolean op(Person friend) {return !friend.isMale();} }; Ops.Op retrieveName = new Ops.Op() { public Object op(Person friend) {return friend.getName();} }; </ul>
  20. 20. <ul>Fork/Join </ul><ul><li>Solve hierarchical problems </li></ul><ul><ul><ul><li>Divide and conquer </li></ul><li>Merge sort, Quick sort
  21. 21. Tree traversal
  22. 22. File scan / search
  23. 23. … </li></ul></ul><ul>[a, b, c, d, e, f, g, h] </ul><ul>[a, b, c, d] </ul><ul>[e, f, g, h] </ul><ul>[a, b] </ul><ul>[c, d] </ul><ul>[e, f] </ul><ul>[g, h] </ul>
  24. 24. <ul>Fork/Join (GPars) </ul><ul>runForkJoin(new File( “./src” )) {currentDir -> long count = 0; currentDir.eachFile { if (it.isDirectory()) { println &quot;Forking a thread for $it&quot; forkOffChild it } else { count++ } } return count + childrenResults .sum(0) } </ul><ul>Waits for children without blocking the thread! </ul>
  25. 25. <ul>Dataflow Concurrency </ul><ul><li>No race-conditions
  26. 26. No live-locks
  27. 27. Deterministic deadlocks </li></ul><ul><ul><li>Completely deterministic programs </li></ul></ul><ul>BEAUTIFUL code </ul><ul><ul><li>(Jonas Bonér) </li></ul></ul>
  28. 28. <ul>Dataflow Variables / Promises </ul><ul>main </ul><ul>task2 </ul><ul>task3 </ul><ul>x </ul><ul>y </ul><ul>z </ul><ul>task1 </ul>
  29. 29. <ul>DataFlows (GPars) </ul><ul>def df = new DataFlows () task { df .z = df .x + df .y } task { df .x = 10 } task { df .y = 5 } assert 15 == df .z </ul>
  30. 30. <ul>Promises (Clojure) </ul><ul>(def x ( promise )) (def y (…))(def z (…)) ( future ( deliver z (+ @x @y))) ( future ( deliver x 10)) ( future ( deliver y 5)) (println @z) </ul>
  31. 31. Milestone <ul><li>Asynchronous background tasks
  32. 32. Parallel collection processing
  33. 33. Fork/Join
  34. 34. Dataflow variables/streams </li></ul>
  35. 35. Message Passing Communicating Sequential Processes (CSP) Dataflow Operators Actors
  36. 36. CSP Stands for Communicating Sequential Processes Highly deterministic Composable
  37. 37. <ul>Dataflow Operators (GPars) </ul><ul>operator(inputs: [stocksStream], outputs: [pricedStocks]) { stock -> def price = getClosing( stock , 2008) bindOutput(0, [stock: stock , price: price ]) } </ul><ul>* </ul><ul>+ </ul><ul><> </ul>
  38. 38. <ul>Actors </ul><ul><li>Isolated
  39. 39. Communicating </li></ul><ul><ul><li>Immutable messages </li></ul></ul><ul><li>Active </li></ul><ul><ul><li>Pooled shared threads </li></ul></ul><ul><li>Activities </li></ul><ul><ul><li>Create a new actor
  40. 40. Send a message
  41. 41. Receive a message </li></ul></ul><ul>Actor </ul><ul>Actor </ul><ul>Actor </ul><ul>Actor </ul><ul>Actor </ul><ul>Actor </ul><ul>Actor </ul><ul>T </ul><ul>T </ul><ul>T </ul><ul>Thread pool </ul>
  42. 42. <ul>Actors use </ul><ul>Gate Keeper </ul><ul>Form </ul><ul>HTTP </ul><ul>Finger Prints </ul><ul>Address Check </ul><ul>Email Check </ul><ul>Process </ul><ul>Fraud Detect </ul><ul>Response </ul><ul>SOAP </ul><ul>SMTP </ul>
  43. 43. <ul>Actors patterns </ul><ul>Enricher Router Translator Endpoint Splitter Agregator Filter Resequencer Checker </ul>
  44. 44. <ul>Creating Actors (GPars) </ul><ul>class MyActor extends AbstractPooledActor { void act() { def buddy = new YourActor().start() buddy << ‘Hi man, how’re things?’ def response = receive () } } </ul>
  45. 45. <ul>Creating Actors (Scala) </ul><ul>val me = actor { loop { react { <li>case w:Work=>reply “I don't work so early”
  46. 46. case b:Breakfast=>
  47. 47. b.eat
  48. 48. react { </li></ul><ul><li>case w:Work=>reply “OK, time to work” ; w.do </li></ul><ul><li>case l:Lunch=>
  49. 49. ...
  50. 50. } } } }
  51. 51. me ! cake </li></ul>
  52. 52. <ul>Continuation Style </ul><ul>loop { … react { … react { /*schedule the block; throw CONTINUE*/ … } //Never reached } //Never reached } //Never reached </ul>
  53. 53. <ul>Creating Actors (Akka - Scala) </ul><ul>class MyActor extends Actor { def receive = { case &quot;Hello&quot; => reply(&quot;World&quot;) case Register(user, sender) => val registrationCode = register(user) sender ! SuccessfulRegistration(registrationCode) case _ => throw new RuntimeException(&quot;unknown message&quot;) } } Example form http://doc.akkasource.org/actors </ul>
  54. 54. <ul>Creating Actors (Jetlang) </ul><ul>Fiber fiber = new ThreadFiber(); fiber .start(); Channel<String> channel = new MemoryChannel<String>(); Callback<String> runnable = new Callback<String>() { public void onMessage (String msg) {     log(msg.toUpperCase());     } }; channel.subscribe( fiber , runnable ); channel.publish( &quot;hello&quot; ); Based on sample code from http://code.google.com/p/jetlang/ </ul>
  55. 55. <ul>Java actor frameworks </ul><ul>Jetlang Kilim ActorFoundry Actorom Akka … </ul>
  56. 56. Shared Mutable State Misused in about 95% of current usages For the remaining 5% use <ul><li>Agents
  57. 57. Software Transactional Memory </li></ul>
  58. 58. <ul>Agent </ul><ul><li>Lock Shared Mutable State in a Safe </li></ul><ul>Alter the State </ul><ul>Alter the State </ul>
  59. 59. <ul>Agent inside </ul><ul>Double </ul><ul>Increment </ul><ul>Add 25 </ul><ul>Message Queue </ul><ul>36 </ul><ul>thread </ul>
  60. 60. <ul>Agent (Clojure) </ul><ul>(defn increment [c] (+ c 1)) (defn decrement [c] (- c 1)) (defn add [c delta] (+ c delta)) (def a ( agent 0)) (send a increment ) | (send a decrement ) | (send a add 25) | … (await a) (println @a) </ul>
  61. 61. <ul>STM (Clojure) </ul><ul>(defstruct person :name :gender :age) (def people (ref #{} )) ( dosync ( alter people conj (struct person &quot;Joe&quot; &quot;male&quot; 39)) ( alter people conj (struct person &quot;Alice&quot; &quot;female&quot; 27)) ( alter people conj (struct person &quot;Dave&quot; &quot;male&quot; 41)) ) </ul>
  62. 62. <ul>STM (Akka - Scala) </ul><ul>atomic { .. // do something within a transaction } atomic (maxNrOfRetries) { .. } atomicReadOnly { .. } atomically { .. // try to do something } orElse { .. // if tx clash; try do do something else } Sample taken from Akka documentation - http://doc.akkasource.org/stm </ul>
  63. 63. Multiverse @ TransactionalObject public class Account{ private int balance; public Account(int initialBalance){...} public int getBalance(){...} public setBalance(int newBalance){...} }
  64. 64. <ul>Persistent Data Structures </ul><ul>Illustration taken from Rich Hickey's presentation. Copyright Rich Hickey 2009 </ul>
  65. 65. <ul>No more threads and locks </ul><ul>images. eachParallel { //concurrency agnostic code here } def myActor = actor { //concurrency agnostic code here } (dosync /*concurrency agnostic code here*/) … </ul>
  66. 66. <ul>Summary </ul><ul><li>Parallelism is not hard, multi-threading is
  67. 67. Jon Kerridge, Napier University </li></ul>
  68. 68. <ul>Tips </ul><ul><li>Java </li></ul><ul><ul><li>JSR-166y - Fork/Join, Parallel Arrays
  69. 69. Multiverse, Jetlang, Kilim, Actorom, ActorFoundry </li></ul></ul><ul><li>Clojure </li></ul><ul><ul><li>STM, Atoms, Agents, Promises </li></ul></ul><ul><li>Scala </li></ul><ul><ul><li>Actors, Akka, ScalaAgent </li></ul></ul><ul><li>Groovy </li></ul><ul><ul><li>GPars – actors, agent, dataflow, fork/join, map/reduce </li></ul></ul>
  70. 70. <ul><li>Questions?
  71. 71. Find more at: </li><ul><li>http://gpars.codehaus.org
  72. 72. http://www.jroller.com/vaclav
  73. 73. http://twitter.com/vaclav_pech </li></ul></ul>

×