Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining...
Transcript of Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining...
![Page 1: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/1.jpg)
Combining Concurrency Abstractions
Philipp HallerTypesafe, Switzerland
Wednesday, December 12, 12
![Page 2: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/2.jpg)
Combining Concurrency Abstractions
Philipp HallerTypesafe, Switzerland
Correctly and Efficiently
Wednesday, December 12, 12
![Page 3: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/3.jpg)
The Problem
• Tendency to combine several concurrency abstractions in a single project
• Actors, futures, threads, latches, ...
• Source of hard-to-diagnose concurrency bugs
• Non-blocking vs. blocking
• Threads vs. thread pools
• Closures and state
Wednesday, December 12, 12
![Page 4: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/4.jpg)
Actors + X
Wednesday, December 12, 12
![Page 5: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/5.jpg)
Actors, State & Futuresimport akka.actor.Actorimport scala.concurrent.future
class MyActor extends Actor { // implicit ExecutionContext of context import context.dispatcher
var state = 0
def receive = { case Request(x) => future { handleRequest(x, state) } case ChangeState(newState) => state = newState }}
Wednesday, December 12, 12
![Page 6: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/6.jpg)
Actors, State & Futuresimport akka.actor.Actorimport scala.concurrent.future
class MyActor extends Actor { // implicit ExecutionContext of context import context.dispatcher
var state = 0
def receive = { case Request(x) => future { handleRequest(x, state) } case ChangeState(newState) => state = newState }}
racy!!
Wednesday, December 12, 12
![Page 7: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/7.jpg)
Actors, State & Futuresimport akka.actor.Actorimport scala.concurrent.future
class MyActor extends Actor { // implicit ExecutionContext of context import context.dispatcher
var state = 0
def receive = { case Request(x) => future { handleRequest(x, state) } case ChangeState(newState) => state = newState }}
racy!!
not safely published!
Wednesday, December 12, 12
![Page 8: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/8.jpg)
Safely Publishing Stateimport akka.actor.Actorimport scala.concurrent.future
class MyActor extends Actor { // implicit ExecutionContext of context import context.dispatcher
var state = 0
def receive = { case Request(x) => val currentState = state future { handleRequest(x, currentState) } case ChangeState(newState) => state = newState }}
Wednesday, December 12, 12
![Page 9: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/9.jpg)
Actors, Futures & Senders
import akka.actor.Actorimport scala.concurrent.future
class MyActor extends Actor { // implicit ExecutionContext of context import context.dispatcher
def receive = { case Request(x) => future { val res = handleRequest(x) sender ! Response(res) } }}
Wednesday, December 12, 12
![Page 10: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/10.jpg)
Actors, Futures & Senders
import akka.actor.Actorimport scala.concurrent.future
class MyActor extends Actor { // implicit ExecutionContext of context import context.dispatcher
def receive = { case Request(x) => future { val res = handleRequest(x) sender ! Response(res) } }} not constant!!
Wednesday, December 12, 12
![Page 11: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/11.jpg)
The Pipe Patternimport akka.actor.Actorimport akka.pattern.pipeimport scala.concurrent.futureclass MyActor extends Actor { // implicit ExecutionContext of context import context.dispatcher
def receive = { case Request(x) => future { val res = handleRequest(x) Response(res) } pipeTo sender }}
Wednesday, December 12, 12
![Page 12: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/12.jpg)
The Pipe Patternimport akka.actor.Actorimport akka.pattern.pipeimport scala.concurrent.futureclass MyActor extends Actor { // implicit ExecutionContext of context import context.dispatcher
def receive = { case Request(x) => future { val res = handleRequest(x) Response(res) } pipeTo sender }}
obtain sender once and store it
Wednesday, December 12, 12
![Page 13: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/13.jpg)
Actors + Threads
• How to exchange messages between an actor and a regular (JVM) thread?
Wednesday, December 12, 12
![Page 14: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/14.jpg)
Actors + Threads
• ask pattern (? operator):
• akka.actor.ActorDSL.Inbox (Akka 2.1)
implicit val i = ActorDSL.inbox()someActor ! someMsg // replies will go to `i`
val reply = i.receive()val transformedReply = i.select(5.seconds) { case x: Int => 2 * x}
val fut = actor ? msg
• How to exchange messages between an actor and a regular (JVM) thread?
Wednesday, December 12, 12
![Page 15: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/15.jpg)
A MapActor (not remote)
import akka.actor.Actor
class MapActor[K, V] extends Actor { var state = Map[K, V]()
def receive = { case Put(k, v) => state += (k -> v) sender ! AckPut case Get(k) => sender ! state.get(k) }}
Wednesday, December 12, 12
![Page 16: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/16.jpg)
A MapActor (not remote)
import akka.actor.Actor
class MapActor[K, V] extends Actor { var state = Map[K, V]()
def receive = { case Put(k, v) => state += (k -> v) sender ! AckPut case Get(k) => sender ! state.get(k) }}
just use a ParTrieMap! :-)
Wednesday, December 12, 12
![Page 17: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/17.jpg)
Miscellaneous
• Thread locals
• Scope: thread, not actor or future callback chain
• Shared-memory actors (same JVM)
• Prefer sharing immutable data
• Mutable data: Java Memory Model (@volatile etc.)
Wednesday, December 12, 12
![Page 18: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/18.jpg)
Combining Async and Blocking APIs
Wednesday, December 12, 12
![Page 19: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/19.jpg)
Blocking APIs
• java.lang.Object.wait
• java.io.Reader.read etc.
• java.util.concurrent: Future.get, CountDownLatch.await, BlockingQueue.put/take
• Scala 2.10 (SIP-14): Await.{result, ready}
• ...
Wednesday, December 12, 12
![Page 20: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/20.jpg)
Blocking Futures
import scala.concurrent._import java.util.concurrent.{Future => JFuture}import ExecutionContext.Implicits.global
object Main extends App {
val futs: List[JFuture[String]] = // list of 4’000 Java futures
val transformed = for (fut <- futs) yield future { fut.get(10, TimeUnit.SECONDS).toUpperCase }}
Wednesday, December 12, 12
![Page 21: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/21.jpg)
Managed Blocking
import scala.concurrent._import java.util.concurrent.{Future => JFuture}import ExecutionContext.Implicits.global
object Main extends App {
val futs: List[JFuture[String]] = // list of 4’000 Java futures
val transformed = for (fut <- futs) yield future { blocking { fut.get(10, TimeUnit.SECONDS).toUpperCase } }}
Wednesday, December 12, 12
![Page 22: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/22.jpg)
Fully Async
import scala.concurrent._
import ExecutionContext.Implicits.global
object Main extends App {
val futs: List[Future[String]] = // list of 4’000 Scala futures
val transformed = for (fut <- futs) yield fut.map(_.toUpperCase) }
Wednesday, December 12, 12
![Page 23: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/23.jpg)
Preventing Misuse
Wednesday, December 12, 12
![Page 24: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/24.jpg)
Requiring Managed Blocking
trait Awaitable[+T] { def result(atMost: Duration) (implicit permit: CanAwait): T}package concurrent { @implicitNotFound("Use the `Await` object") sealed trait CanAwait
private[concurrent] object AwaitPermission extends CanAwait
object Await { def result[T](awaitable: Awaitable[T], ...): T = blocking(awaitable.result(atMost)(AwaitPermission)) }}
Wednesday, December 12, 12
![Page 25: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/25.jpg)
Your Turn!
• What do you find hard/confusing when combining concurrency abstractions?
• What practices do you follow/recommend to avoid concurrency hazards?
Wednesday, December 12, 12
![Page 26: Combining Concurrency Abstractions - EPFLlampphaller/doc/Combining_Concurrency.pdf · Combining Concurrency Abstractions Philipp Haller Typesafe, Switzerland Correctly and Efficiently](https://reader030.fdocuments.in/reader030/viewer/2022041105/5f0727207e708231d41b91a7/html5/thumbnails/26.jpg)
Thanks! Questions?Philipp Haller
Typesafe, Switzerland
Wednesday, December 12, 12