78
State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVM TM Jonas Bonér Crisp AB http://jonasboner.com http://crisp.se

State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

  • Upload
    lamnhu

  • View
    222

  • Download
    0

Embed Size (px)

Citation preview

Page 1: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM

Jonas BonérCrisp ABhttp://jonasboner.comhttp://crisp.se

Page 2: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

2

Agenda> An Emergent Crisis> Shared-State Concurrency> Message-Passing Concurrency (Actors) > Software Transactional Memory (STM)> Dataflow Concurrency> Wrap up

Page 3: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

3

Moore’s Law> The number of transistors are doubling every 18

months > Coined in the 1965 paper by Gordon E. Moore > Chip manufacturers have solved our problems for

years

Page 4: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

4

Not anymore

Page 5: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

5

The free lunch is over> The end of Moore’s Law > We can’t squeeze more out of one chip

Page 6: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

6

Clock speed vs number of transistors

> The number of transistors continues to climb, at least for now > Clock speed, however, is a different story

Page 7: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

7

Conclusion> This is an emergent crisis > Multi-processors are here to stay > We need to learn to take advantage of that > The world is going concurrent

Page 8: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

8

The rise of Amdahl’s Law

“The speedup of a program using multiple processors in parallel

computing is limited by the time needed for the sequential fraction of

the program”

Page 9: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

9

Shared-State Concurrency> Concurrent synchronized access to shared,

mutable state. > Protect mutable state with locks > The

Java C# C/C++ Ruby Python etc. way

Page 10: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

10

Shared-State Concurrency is incredibly hard> Inherently very hard to use reliably> Even the experts get it wrong

Page 11: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

11

Example: Transfer funds between bank accounts

Page 12: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

12

Accountpublic class Account {   private double balance;    public void withdraw(double amount) {  balance -= amount;  }    public void deposit(double amount) {  balance += amount;  }  } > Not thread-safe 

Page 13: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

13

Make it thread-safepublic class Account {   private double balance;    public synchronized void withdraw(double amount) {  balance -= amount;  }    public synchronized void deposit(double amount) {  balance += amount;  }  } > Thread-safe, right? > What about atomic transfers?  

Page 14: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

14

Let’s write a transfer methodpublic synchronized void transfer( Account from, Account to, double amount) {    from.withdraw(amount);    to.deposit(amount);  }  > This will work right?

Page 15: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

15

It’s broken> Someone might update the account outside our

transfer method

Page 16: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

16

Transfer method; take 2public void transfer( Account from, Account to, double amount) {    synchronized(from) {     synchronized(to) {       from.withdraw(amount);        to.deposit(amount);      }    }  }  > This will work right?

Page 17: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

17

Let’s transfer fundsAccount a1 = ...  Account a2 = ...    // in one thread  transfer(a1, a2, 10.0D);    // in another thread  transfer(a2, a1, -3.0D); 

Page 18: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

18

Might lead to DEADLOCK!!!> Darn, this is really hard!!!

Page 19: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

19

We need to enforce lock ordering> How? > Java won’t help us > Need to use code convention (names etc.) > Requires knowledge about the internal state and

implementation of Account > …runs counter to the principles of encapsulation

in OOP > Opens up a Can of Worms™

Page 20: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

20

The devil is in the mutable state

Page 21: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

21

The problem with locks> Locks do not compose > Ordering matters but can’t be enforced

Need to rely on code conventions > Not natural to reason about

Does not map well to the real world > Easy to get

Deadlocks Live locks Starvation

Page 22: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

22

Jonas’ Law ;-)

“Shared-State Concurrency is like children;

completely indeterministic behavior with a risk for total deadlock.”

Page 23: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

23

Help 1: java.util.concurrent> Great library > Raises the abstraction level > Simplifies concurrent code > Use it, don’t roll your own

Page 24: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

24

Help 2: Immutable objects> Can be safely shared between threads > Easy to reason about > Less bug and error prone > Should be the default (final in Java) > Effectively immutable objects are OK

Page 25: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

25

Help 3: Confinement> Thread confinement

ThreadLocal in Java > Stack confinement

Page 26: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

26

Java bet on the wrong horse> But there are alternatives > There is actually a better world out there…

Page 27: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

27

Alternative paradigms> Message-Passing Concurrency (Actors) > Software Transactional Memory (STM) > Dataflow Concurrency

Page 28: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

28

Message-Passing Concurrency

Page 29: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

29

Actors> Implements Message-Passing Concurrency> Share NOTHING> Isolated lightweight processes> Communicates through messages> Asynchronous and non-blocking

Page 30: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

30

Actors> Originates in a 1973 paper by Carl Hewitt> Implemented in Erlang, Occam, Oz> Encapsulates state and behavior> Closer to the definition of OO than classes

Page 31: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

31

Alan Kay (father of SmallTalk and OOP)

“OOP to me means only messaging, local retention and protection and

hiding of state-process, and extreme late-binding of all things.”

“Actually I made up the term “object-oriented”, and I can tell you

I did not have C++ in mind.Replace C++ with Java or C#

Page 32: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

32

Actor Model of Concurrency > No shared state

… hence, nothing to synchronize.> Each actor has a mailbox (message queue)

Page 33: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

33

Actor Model of Concurrency> Non-blocking send> Blocking receive> Messages are immutable> Highly performant and scalable

SEDA-style

Page 34: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

34

Actor Model of Concurrency > Easier to reason about> Raised abstraction level> Easier to avoid

Race conditions Deadlocks Starvation Live locks

Page 35: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

35

Fault-tolerant systems > Link actors> Supervisor hierarchies

One-for-one All-for-one

> Ericsson’s Erlang success story 9 nines uptime

Page 36: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

36

Scala Actors> Asynchronous

Fire-and-forget Futures (Send Receive Reply Eventually)

> Synchronous> Message loop with pattern (message) matching> Erlang-style

Page 37: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

37

Example: Hello Worldval server = actor {     loop {    // message loop   react { // match on message        case "greeting" =>          println("Hello World!")          case "exit" =>           println("Exiting")            exit        case _  =>          println("Unknown message")        }      }    }    

Page 38: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

38

Two different models> Thread-based

receive { ... }> Event-based

react { ... } Very lightweight Can easily create millions on a single workstation

> The models are unified

Page 39: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

39

Example: Ship scheduling system > Uses Event Sourcing

Capture all changes to an application state as a sequence of events

Page 40: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

40

Define the messagessealed abstract case class Event  abstract case class StateChange(val time Date) extends Event {  val recorded = new Date    def process: Unit  }  

case class DepartureEvent( val time: Date, val port: Port, val ship: Ship)     extends StateChange(time) {    override def process = ship ! this  }  

case class ArrivalEvent( val time: Date, val port: Port, val ship: Ship)     extends StateChange(time) {    override def process = ship ! this  }  

Page 41: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

41

Create the Ship actor class Ship(val name: String, val home: Port) extends Actor {    def act = loop(home)        private def loop(current: Port) {  react {     case ArrivalEvent(time, port, _) =>        println(toString + " ARRIVED  at port " + port + " @ " + time)         loop(port)       case DepartureEvent(time, port, _) =>        println(toString + " DEPARTED from port " + port  + " @ " + time)         loop(Port.AT_SEA)       case unknown =>          error("Unknown event: " + unknown)     }   }}

Page 42: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

42

Create the EventProcessor actor class EventProcessor extends Actor {    def act = loop(Nil)    private def loop(log: List[StateChange]) {     react {        case event: StateChange =>           event.process          loop(event :: log)        case unknown =>           error("Unknown event: " + unknown)      }    }  }  

Page 43: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

43

Create the Ship, EventProcessor and Ports

val processor = new EventProcessor  processor.start       val portSFO = new Port("San Francisco", Country.US)  val portLA = new Port("Los Angeles", Country.US)  val portYYV = new Port("Vancouver", Country.CANADA)    val shipKR = new Ship("King Roy", portYYV)  shipKR.start  

Page 44: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

44

Set the Ship to sea processor ! ArrivalEvent(new Date(..), portLA, shipKR)    processor ! DepartureEvent(new Date(..), portYYV, shipKR)    processor ! ArrivalEvent(new Date(..), portYYV, shipKR)  

processor ! DepartureEvent(new Date(..), portSFO, shipKR)    processor ! ArrivalEvent(new Date(..), portSFO, shipKR)  

Page 45: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

45

Add replay of messages case object Replay extends Event   class EventProcessor extends Actor {      def act = loop(Nil)            private def loop(log: List[StateChange]) {       react {         ...          // replay all events        case Replay =>             log.reverse.foreach(_.process)             loop(log)        }      }    }    

Page 46: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

46

Add replay of up to a specific date (e.g. snapshot)

case class ReplayUpTo(date: Date) extends Event    class EventProcessor extends Actor {    def act = loop(Nil)    private def loop(log: List[StateChange]) {      react {        ...        // replay events up to a specific time        case ReplayUpTo(date) =>          log.reverse .filter(_.occurred.getTime <= date.getTime)            .foreach(_.process)           loop(log)      }    }  }  

Page 47: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

47

Priority Messagesdef act = loop(Nil)  private def loop(log: List[StateChange]) {   reactWithin(0) {   case ArrivalEvent(time, port, _) =>    ... // highest priority        react {    case DepartureEvent(time, port, _)  ... // lowest priority        }    }  }  

Page 48: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

48

Actor alternatives for the JVM > Killim (Java)> Jetlang (Java)> Actor’s Guild (Java)> ActorFoundry (Java)> Actorom (Java)> GParallelizer (Groovy)> Fan Actors (Fan)

Page 49: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

49

Problems with Actors> Actors don’t work well when

We really have shared state. F.e. bank account We need to form some unified consensus We need synchronous behavior

> A bit verbose compared to method dispatch

Page 50: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

50

Software Transactional Memory (STM)

Page 51: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

51

STM> See the memory (heap and stack) as a

transactional dataset> Similar to a database

begin commit abort/rollback

Page 52: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

52

STM> Transactions are retried automatically upon

collision> Rolls back the memory on abort

Page 53: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

53

STM> Transactions can nest> Transactions compose atomic {    ..    atomic {       ..     }   }  

Page 54: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

54

Developer restrictions > All operations in scope of a transaction:

Needs to be idempotent Can’t have side-effects

Page 55: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

55

Case study: Clojure

Page 56: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

56

What is Clojure? > Functional language> Only immutable data and datastructures> Pragmatic Lisp> Great Java interop> Dynamic, but very fast

Page 57: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

57

Clojure’s concurrency story > STM (Refs)

Synchronous Coordinated> Atoms

Synchronous Uncoordinated> Agents

Asynchronous Uncoordinated> Vars

Synchronous Thread Isolated

Page 58: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

58

STM (Refs)> A Ref holds a reference to an immutable value> A Ref can only be changed in a transaction> Updates are atomic and isolated (ACI)> A transaction sees its own snapshot of the world> Transactions are retried upon collision

Page 59: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

59

Agents> Manages independent state> Asynchronous (fire-and-forget)> Changes state by applying a function (state =>

newState)> Coordinates with STM (changes are held until

commit)

Page 60: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

60

Atoms> Manages independent state> Synchronous> Atomic transition

Page 61: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

61

Clojure’s STM implementation > MVCC (Multi-Version Concurrency Control)> Uses wait/notify> Deadlock detection> One single CAS (timestamp)

Page 62: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

62

Example: Refs (def foo (ref {:a "fred" :b "ethel" :c 42 :d 17 :e 6}))  @foo   ;; -> {:d 17, :a "fred", :b "ethel", :c 42, :e 6}    (commute foo assoc :a "lucy")   ;; -> IllegalStateException: No transaction running    (dosync (commute foo assoc :a "lucy"))  @foo   ;; -> {:d 17, :a "lucy", :b "ethel", :c 42, :e 6}  

Page 63: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

63

Uniformed state transition

;; refs  (dosync (commute foo  assoc :a "lucy"))    ;; agents  (send foo assoc :a "lucy")    ;; atoms  (swap! foo assoc :a "lucy")  

Page 64: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

64

My (humble) opinion on STM > Can never work fine in a language that don’t

have compiler enforced immutability> E.g. never in Java

> Still a research topic how to do it in imperative languages

Page 65: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

65

Dataflow Concurrency> The forgotten paradigm

Page 66: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

66

Dataflow Concurrency> Declarative > No observable non-determinism > Data-driven – threads blocks until data is available > No difference between concurrent and sequential

code

Page 67: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

67

Dataflow Concurrency> Dataflow (Single-Assignment) Variables > Dataflow Streams (the tail is a dataflow variable) > Implemented in Oz and Alice

Page 68: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

68

Dataflow Concurrency> No race-conditions > No deadlocks > No live-locks > Deterministic > BEAUTIFUL

Page 69: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

69

Three operations> Create a dataflow variable > Wait for the variable to be bound > Bind the variable

Page 70: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

70

Limitations> Can’t have side-effects

Exceptions IO etc.

Page 71: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

71

Example: Oz-style dataflow concurrency for the JVM> Created my own implementation (DSL) > Implemented on top in Scala

Page 72: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

72

API: Dataflow Variable// Create dataflow variable  val x, y, z = new DataFlowVariable[Int]    // Access dataflow variable (Wait to be bound)  z()    // Bind dataflow variable  x << 40    // Lightweight thread  thread { y << 2 }  

Page 73: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

73

Example: Dataflow Variables

val x, y, z = new DataFlowVariable[Int]  thread {      z << x() + y()      println("z = " + z())  }  thread { x << 40 }  thread { y << 2 }  

Page 74: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

74

API: Dataflow Stream

// Create dataflow stream  val producer = new DataFlowStream[Int]    // Append to stream  producer <<< s    // Read from stream  producer()  

Page 75: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

75

Example: Dataflow Streamsdef ints(n: Int, max: Int, stream: DataFlowStream[Int]) = { if (n != max) {      stream <<< n     ints(n + 1, max, stream)   }}def sum(s: Int, in: DataFlowStream[Int],  out: DataFlowStream[Int]): Unit = {     out <<< s    sum(in() + s, in, out)  }  def printSum(stream: DataFlowStream[Int]) = {    println("Result: " + stream())          printSum(stream)  }  

Page 76: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

76

Example: Dataflow Streams

val producer = new DataFlowStream[Int]  val consumer = new DataFlowStream[Int]    thread { ints(0, 1000, producer) }  thread { sum(0, producer, consumer) }  thread { printSum(consumer) }  

Page 77: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

77

Wrap up> Parallel programs is becoming increasingly

important> We need a simpler way of writing concurrent

programs> Java-style concurrency is too hard> There are alternatives worth exploring

Message-Passing Concurrency Software Transactional Memory Dataflow Concurrency

Page 78: State You’re Doing it Wrong: Alternative Concurrency ... · State You’re Doing it Wrong: Alternative Concurrency Paradigms For the JVMTM ... C/C++ Ruby Python ... > No difference

78

Jonas BonérCrisp ABhttp://jonasboner.comhttp://crisp.se