concurrency · making code transactional @transactional public void findallfoosaround() {//tx...

38
Concurrency Unleash your processor(s) Václav Pech

Upload: others

Post on 08-Jul-2020

7 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Concurrency

Unleash your processor(s)Václav Pech

Page 2: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

The evil accumulator

int sum=0;for(int i : collection) sum += i;

Page 3: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

We’re quad core already

Beware: More cores to come shortly!

Page 4: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Stone age of parallel SW

Dead-locks Live-locks Race conditions Starvation

Shared Mutable State

Page 5: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Lock and synchronize

Multithreaded programs today work mostly by accident!

Page 6: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Making code transactional

@Transactionalpublic void findAllFoosAround() { //tx agnostic code here}

withTransaction { //tx agnostic code here}

Page 7: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Map/Reduce

Fork/Join

Actors

STM

Dataflow

Agent

Can we do better?

Page 8: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Collections (GPars)

images.eachParallel {it.process()}

documents.sumParallel()

candidates.maxParallel {it.salary}.marry()

Page 9: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Parallel Arrays (jsr-166y)

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();}};

Page 10: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Fork/Join

Solve hierarchical problems

Divide and conquer Merge sort, Quick sort Tree traversal File scan / search …

[a, b, c, d, e, f, g, h]

[a, b, c, d] [e, f, g, h]

[a, b] [c, d] [e, f] [g, h]

Page 11: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Fork/Join (GPars)

protected void computeTask() { long count = 0; file.eachFile { if (it.isDirectory()) { println "Forking a thread for $it" forkOffChild(new FileCounter(it)) } else { count++ } } return count + childrenResults.sum() }

Waits for children without blocking the thread!

Page 12: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Asynchronous invocation

Future f = threadPool.submit(calculation);…System.out.println(“Result: “ + f.get());

main calculation

get()

Page 13: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Dataflow Concurrency

No race-conditions No live-locks Deterministic deadlocks

Completely deterministic programs

BEAUTIFUL code (Jonas Bonér)

Page 14: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Dataflow Variables / Promisesmain task2 task3

x

yz

task1

Page 15: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

DataFlows (GPars)

def df = new DataFlows()

task { df.z = df.x + df.y }task { df.x = 10 }task { df.y = 5 }

assert 15 == df.z

Page 16: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Promises (Clojure)

(def x (promise)) (def y (…))(def z (…))

(future (deliver z (+ @x @y)))(future (deliver x 10))(future (deliver y 5))

(println @z)

Page 17: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Dataflow Operators (GPars)

operator(inputs: [stocksStream], outputs: [pricedStocks]) {stock -> def price = getClosing(stock, 2008) bindOutput(0, [stock: stock, price: price]) }

*

+<>

Page 18: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Actors

Isolated Communicating

Immutable messages Active

Pooled shared threads Activities

Create a new actorSend a messageReceive a message

ActorActorActorActorActorActorActor

TTTThread pool

Page 19: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Actors use

GateKeeper

Form

HTTP

FingerPrints

AddressCheck

EmailCheckProcess

FraudDetect

Response

SOAP

SMTP

Page 20: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Actors patternsEnricher

Router

Translator

Endpoint

Splitter

Agregator

Filter

Resequencer

Checker

Page 21: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Creating Actors (GPars)

class MyActor extends AbstractPooledActor { void act() { def buddy = new YourActor() buddy << ‘Hi man, how\’re things?’ def response = receive() }}

Page 22: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Creating Actors (Scala)

val myActor = actor { loop { react { case x:Int=>reply 2*x case s:String=>reply s.toUpperCase() } }}myActor ! 10

Page 23: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Creating Actors (Akka - Scala)

class MyActor extends Actor { def receive = { case "Hello" => reply("World") case Register(user, sender) => val registrationCode = register(user) sender ! SuccessfulRegistration(registrationCode) case _ => throw new RuntimeException("unknown

message")} }

Example form http://doc.akkasource.org/actors

Page 24: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Continuation Style

loop { … react { … react {/*schedule the block; throw CONTINUE*/ … } //Never reached } //Never reached}//Never reached

Page 25: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Creating Actors (Jetlang)

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("hello");

Based on sample code from http://code.google.com/p/jetlang/

Page 26: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Java actor frameworks

JetlangKilimActorFoundryActoromAkka…

Page 27: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Agent

Lock Shared Mutable State in a Safe

Alterthe

State

Alterthe

State

Page 28: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Agent inside

Double IncrementAdd 25

Message Queue

36 thread

Page 29: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Agent (Clojure)

(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)

Page 30: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Agent (ScalaAgent)

def increment(x: Long) = x + 1def decrement(delta : Long)(x: Long) = x - delta val agent = Agent(0L)

agent(increment _) agent(decrement(3) _) agent{_ + 100} println(agent get)

Page 31: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

STM (Clojure)

(defstruct person :name :gender :age)(def people (ref #{}))

(dosync (alter people conj (struct person "Joe" "male" 39)) (alter people conj (struct person "Alice" "female" 27)) (alter people conj (struct person "Dave" "male" 41)))

Page 32: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

STM (Akka - Scala)

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

Page 33: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Persistent Data Structures

Illustration taken from Rich Hickey's presentation. Copyright Rich Hickey 2009

Page 34: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Our original intention

@Transactionalpublic void findAllFoosAround() { //tx agnostic code here}

withTransaction { //tx agnostic code here}

Page 35: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

The reality

images.eachParallel { //concurrency agnostic code here}

def myActor = actor { //concurrency agnostic code here}

(dosync /*concurrency agnostic code here*/)…

Page 36: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Summary

Parallelism is not hard, multi-threading is

Systems that interface to the real world are easier to design in parallel

Jon Kerridge, Napier University

Page 37: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Tips

Java JSR-166y - Fork/Join, Parallel Arrays, Multiverse

Clojure STM, Atoms, Agents, Promises

Scala Actors, Akka, ScalaAgent

Groovy GPars – actors, agent, dataflow, fork/join, map/reduce

Page 38: Concurrency · Making code transactional @Transactional public void findAllFoosAround() {//tx agnostic code here} withTransaction {//tx agnostic code here}

Questions?