Groovy concurrency
-
Upload
alex-miller -
Category
Technology
-
view
2.581 -
download
3
description
Transcript of Groovy concurrency
![Page 1: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/1.jpg)
Groovy ConcurrencyAlex MillerRevelytix
![Page 2: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/2.jpg)
• Groovy library - http://gpars.codehaus.org/
• Open-source
• Great team: Václav Pech, Dierk König, Alex Tkachman, Russel Winder, Paul King
• Integration with Griffon, Grails, etc
GParsJeepers!
![Page 3: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/3.jpg)
Concurrency Patterns
• Asynchronous processing
• Computational processing
• Managing mutable state
• Actor messaging
• Agents
• Dataflow variables
![Page 4: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/4.jpg)
Asynchronous Processing
Improve perceived performance by pushing I/O-bound work onto a different thread.
![Page 5: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/5.jpg)
Serialized Processingmain
Retrieve user1 tweets
Retrieve user2 tweets
Process tweets
![Page 6: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/6.jpg)
Asynchronous Processing
main background 1
Request user1 tweets
Process tweets
background 2
Retrieve user1 tweets Retrieve
user2tweets
Request user2 tweets
![Page 7: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/7.jpg)
GParsExecutorsPool• Leverages java.util.concurrent.Executor
• void execute(Runnable command)
• Decouple task submission from task execution
• GParsExecutorsPool.withPool() blocks add:
• async() - takes closure, returns Future
• callAsync() - same, but takes args
![Page 8: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/8.jpg)
Future
• Future represents the result of an asynchronous computation
• Poll for results, block till available, etc
• Cancel, check for cancellation
![Page 9: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/9.jpg)
GParsExecutorsPool.withPool { def retrieveTweets = { query -> recentTweets(api, query) }
trends.each { retrieveTweets.callAsync(it.query) }}
trends.each { retrieveTweets(api, it.query)}
![Page 10: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/10.jpg)
Computational Processing
Use multiple cores to reduce the elapsed time of some cpu-bound work.
![Page 11: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/11.jpg)
Executor PoolsSame pools used for asynch are also good for transaction processing. Leverage more cores to process the work.
T1
Task 1
Task 2
Task 3
Task 4
Task 5
Task 6
T1
Task 1
Task 4
T2
Task 2
Task 5
T3
Task 3
Task 6
![Page 12: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/12.jpg)
Work pools and Queues
takeput
queue
![Page 13: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/13.jpg)
Fork/Join Pools
• DSL for new JSR 166y construct (JDK 7)
• DSL for ParallelArray over fork/join
• DSL for map/reduce and functional calls
![Page 14: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/14.jpg)
Fork/Join Pools
takeput
queue
takeput
queue
takeput
queue
![Page 15: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/15.jpg)
Fork/Join vs Executors• Executors (GParsExecutorsPool) tuned for:
• small number of threads (4-16)
• medium-grained I/O-bound or CPU-bound tasks
• Fork/join (GParsPool) tuned for:
• larger number of threads (16-64)
• fine-grained computational tasks, possibly with dependencies
![Page 16: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/16.jpg)
Divide and Conquer
Task: Find max value in an array
![Page 17: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/17.jpg)
Divide and Conquer
![Page 18: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/18.jpg)
Divide and Conquer
![Page 19: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/19.jpg)
ParallelArray
• Most business problems don’t really look like divide-and-conquer
• Common approach for working in parallel on a big data set is to use an array where each thread operates on independent chunks of the array.
• ParallelArray implements this over fork/join.
![Page 20: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/20.jpg)
ParallelArrayOrder2/15
Order5/1
Order1/15
Order3/15
Order2/1
Order4/1
Starting ordersw/due dates
Filter only overdue Order2/15
Order1/15
Order2/1
Map to days overdue
Avg
45 3015
30 days
![Page 21: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/21.jpg)
ParallelArray usage
def isLate = { order -> order.dueDate > new Date() }def daysOverdue = { order -> order.daysOverdue() }
GParsPool.withPool { def data = createOrders() .filter(isLate) .map(daysOverdue)
println("# overdue = " + data.size()) println("avg overdue by = " + (data.sum() / data.size()))}
![Page 22: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/22.jpg)
Managing Mutable State
![Page 23: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/23.jpg)
The Java
concurrency
bible
![Page 24: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/24.jpg)
• It’s the mutable state, stupid.
• Make fields final unless they need to be mutable.
• Immutable objects are automatically thread-safe.
• Encapsulation makes it practical to manage the complexity.
• Guard each mutable variable with a lock.
• Guard all variables in an invariant with the same lock.
• Hold locks for the duration of compound actions.
• A program that accesses a mutable variable from multiple threads without synchronization is a broken program.
• Don’t rely on clever reasoning about why you don’t need to synchronize.
• Include thread safety in the design process - or explicitly document that your class is not thread-safe.
• Document your synchronization policy.
JCIP
![Page 25: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/25.jpg)
• It’s the mutable state, stupid.
• Make fields final unless they need to be mutable.
• Immutable objects are automatically thread-safe.
• Encapsulation makes it practical to manage the complexity.
• Guard each mutable variable with a lock.
• Guard all variables in an invariant with the same lock.
• Hold locks for the duration of compound actions.
• A program that accesses a mutable variable from multiple threads without synchronization is a broken program.
• Don’t rely on clever reasoning about why you don’t need to synchronize.
• Include thread safety in the design process - or explicitly document that your class is not thread-safe.
• Document your synchronization policy.
JCIP
![Page 26: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/26.jpg)
The problem with shared state concurrency...
![Page 27: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/27.jpg)
The problem with shared state concurrency...
is the shared state.
![Page 28: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/28.jpg)
Actors
• No shared state
• Lightweight processes
• Asynchronous, non-blocking message-passing
• Buffer messages in a mailbox
• Receive messages with pattern matching
• Concurrency model popular in Erlang, Scala, etc
![Page 29: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/29.jpg)
Actors
![Page 30: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/30.jpg)
start
Actors
![Page 31: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/31.jpg)
start
send
Actors
![Page 32: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/32.jpg)
receive
Actors
![Page 33: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/33.jpg)
Actor Example
class Player extends AbstractPooledActor { String name def random = new Random()
void act() { loop { react { // player replies with a random move reply Move.values()[random.nextInt(Move.values().length)] } } }}
![Page 34: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/34.jpg)
Agent• Like Clojure Agents
• Imagine wrapping an actor around mutable state...
• Messages are:
• functions to apply to (internal) state OR
• just a new value
• Can always safely retrieve value of agent
![Page 35: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/35.jpg)
def stuff = new Agent<List>([])
// thread 1stuff.send( {it.add(“pizza”)} )
// thread 2 stuff.send( {it.add(“nachos”)} )
println stuff.val
Simple example...• Use generics to specify data type of wrapped data
• Pass initial value on construction
• Send function to modify state
• Read value by accessing val
![Page 36: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/36.jpg)
class BankAccount extends Agent<Long> { def BankAccount() { super(0) } private def deposit(long deposit) { data += deposit } private def withdraw(long deposit) { data -= deposit }}
final BankAccount acct = new BankAccount()
final Thread atm2 = Thread.start { acct << { withdraw 200 }}
final Thread atm1 = Thread.start { acct << { deposit 500 }}
[atm1,atm2]*.join()println "Final balance: ${ acct.val }"
![Page 37: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/37.jpg)
Dataflow Variables
• A variable that computes its value when its’ inputs are available
• Value can be set only once
• Data flows safely between variables
• Ordering falls out automatically
• Deadlocks are deterministic
![Page 38: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/38.jpg)
• Logical tasks
• Scheduled over a thread pool, like actors
• Communicate with dataflow variables
Dataflow Tasks
![Page 39: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/39.jpg)
final def x = new DataFlowVariable()final def y = new DataFlowVariable()final def z = new DataFlowVariable()
task { z << x.val + y.valprintln “Result: ${z.val}”
}
task {x << 10
}
task {y << 5
}
Dataflow example
![Page 40: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/40.jpg)
• Bind handlers - can be registered on a dataflow variable to execute on bind
• Dataflow streams - thread-safe unbound blocking queue to pass data between tasks
• Dataflow operators - additional abstraction, formalizing inputs/outputs
Dataflow support
![Page 41: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/41.jpg)
Sir Not-Appearing-In-This-Talk
• Caching - memoize
• CSP
• GPU processing
![Page 42: Groovy concurrency](https://reader031.fdocuments.in/reader031/viewer/2022020110/555c2578d8b42a09438b4c2b/html5/thumbnails/42.jpg)
Alex Miller
Twitter: @puredanger
Blog: http://tech.puredanger.com
Code:
http://github.com/puredanger/gpars-examples
Conference: Strange Loop
http://strangeloop2010.com