Concurrency On The JVM
Concurrency On The JVM
Concurrency On The JVM
Executors
Fork / Join Framework
Actors
Th Letschert, THM
Seite 2
Speed
Exploit the power of working in parallel: distribution, multi-cores, DMAs, ...
Perils
Development of concurrent app. is more demanding
Deadlocks
Starvation
Race Conditions
Non-deterministic behavior
...
Seite 3
Create
Create object
Start
Call start-Method
Stop
Mutual Exclusion
synchronized
method
synchronized
block
Conditional Synchronization
wait
notify
notifyAll
Basic Ideas
Monitor = Class + Synchronization
Localize resources and their associated methods and synchronization in one entity
Synchronization
Solve race conditions
Solve conditional synchronization
Mutual Exclusion
Race conditions are solved by mutual exclusion
Conditional Synchronization
Preconditions: Some operations can be performed only if a condition holds
wait / notify:
Seite 5
Conceptual
Token place;
boolean empty = true;
// one call must not interfere with other calls
// Precondition: empty
void put(Token t) {
place = t;
empty = false;
}
// one call must not interfere with other calls
// Pre: not empty
class PlaceMonitor {
Token get() {
empty = true;
Token place;
return place;
boolean empty = true;
}
synchronized void put(Token t) throws InterruptedException {
while ( ! empty ) wait();
place = t;
empty = false;
notify();
}
}
Seite 6
Seite 7
Seite 8
Seite 9
Task 2
Task 4
Task 1
Task 3
threads
Task 5
Machine
Problem
Seite 10
Task 5
Executor
threads
Seite 11
Request_Tasks
the net
java.io.IOException;
java.net.DatagramPacket;
java.net.DatagramSocket;
java.util.concurrent.Executor;
java.util.concurrent.Executors;
dtgrmSocket.receive(rcvpkt);
Request_Task rqT = new Request_Task(rcvpkt);
executor.execute(rqT);
} catch (IOException e) {}
}
} catch (IOException e) {}
}
}
Seite 12
client
thread
Task
Immediate response
Future
Future result =
synchronized place where
to put (executor) and take
(client) the result of the
computation.
worker
threads
Seite 13
java.util.LinkedList;
java.util.List;
java.util.concurrent.Callable;
java.util.concurrent.ExecutionException;
java.util.concurrent.ExecutorService;
java.util.concurrent.Executors;
java.util.concurrent.Future;
fl.add(
executor.submit(
new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return someExpensiveOperation(xx);
}
}));
x++;
if (x == 10) break;
Concurrent Collections
ConcurrentHashMap
CopyOnWriteArrayList
CopyOnWriteArraySet
ConcurrentLinkedQueue
ArrayBlockingQueue
Synchronizers
Lock
Condition
Queue / Deque
CyclicBarrier
CountDownLatch
Semaphore
Exchanger
explicit Mutex
explicit Condition variable
Queues used as synchronizer
Barrier
Latch
LinkedBlockingQueue
SynchronousQueue
PrioritiyQueue
DelayQueue
ConcurrentLinkedQueue
Fork-Join Framework
Separates tasks and threads even more
loosening the task thread relation
Introduced with Java 1.7 (in package java.util.concurrent)
threads may be utilized by several computational tasks
Task
Task
Task
Task
Task
Task
Task
Task
Task
Task
Task
Task
Executor
A thread works on its task
until it is completed, then it
takes the next one.
Number of tasks being processed at one time
= number of threads.
A blocking operation blocks the thread!
Blocking while waiting for anther task in the
pool may lead to deadlock.
ForkJoinPool
Number of tasks being processed at one time
may be larger number of threads.
Seite 16
java.util.concurrent.Callable;
java.util.concurrent.ExecutionException;
java.util.concurrent.ExecutorService;
java.util.concurrent.Executors;
java.util.concurrent.Future;
@Override
public Integer call() throws Exception {
return (arg == 0 || arg == 1) ? arg : fib(arg-1) + fib(arg-2);
}
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println("Cores: " + Runtime.getRuntime().availableProcessors());
long start = System.currentTimeMillis();
System.out.println(fib(49));
long stop = System.currentTimeMillis();
System.out.println("duration (ms): " + (end-start));
System.exit(0);
With 8 threads fib(49) can
}
Seite 18
}
Cores: 8
7778742049
duration (ms): 451472
class Matrix {
double [][] m = null;
int lineCount;
int columnCount;
. . .
Recursive computation of
determinate via
determinant of co-matrix
. . .
}
11
21
31
41
12
22
32
42
13
23
33
44
14
24
34
45
22 23 24
11 * 32 33 34 - 21 *
42 44 45
12 13 14
32 33 34 + 31 *
42 44 45
Seite 19
12 13 14
12 13 14
41
*
22 23 24
22 23 24
32 33 34
42 44 45
Ax = b
xi = |Abi | / |A|
12x12 System,
sequential solution :
2'072'903 ms
ForkJoin determinant computation:
725'546 ms
On Intel Core i7 CPU 860 @ 2.80GHz, (8 cores)
Seite 20
Considerable speed-up on
a multi-core system!
Ax = b
xi = |Abi | / |A|
12x12 System
seqential Scala :
parallel Scala :
sequential Java :
ForkJoin Java :
3'045'511 ms
2'854'433 ms
2'072'903 ms
725'546 ms
Seite 21
Fork-Join Framework
Use: Parallel programming where problems
can be recursively split into smaller parts,
solved in parallel
and then recombined
Seite 22
Actors
Actor
What is an Actor?
Actor: some-one/-thing that acts not necessarily in a play or movie
Practice:
Seite 23
Seite 24
Actor Model
An actor is an entity that may
send messages (which are actors) to other actors
create new actors
change its behavior designating how to handle
the next message it receives
No channels
Message transfer is actor to actor
One atomic entity: the actor
The transport medium is intentionally left outside the model :
indeterministic message delivery: a message send will be delivered,
but without any predictable time limit or order
Seite 25
The
completely
unknown
outer space
Actors in Use:
In Search for a Convenient Expression of Concurrency
Malady:
Writing programs in a monitor style, ie.
active entities (processes / threads) working on
shared mutable passive resources
causes pain.
Cure
Write programs that avoid shared mutable state.
No shared state
=> Communication solely through message passing
No mutable state
=> Functional style of programming
Carl Hewitt on the actor model - live:
Seite 26
http://ak.channel9.msdn.com/ch9/01ad/2ca509cc-d410-4663-8679-6ece29cd01ad/LangNEXT2012HewittMeijerSzyperkiActors_mid.mp4
ill be
w
a
k
d Ak lowing.
n
a
a
l
Scal n the fo
n
i
i
rs
d
Acto nsidere
co
Seite 27
http://akka.io/
Seite 28
Seite 29
put
get
producer
buffer
consumer
producer
buffer
Seite 30
consumer
put
get
producer
buffer
consumer
put
get
OK
value
buffer
consumer
if (message is Put-message) {
if (full) {
delay(message);
} else {
full = true;
store = message.getV();
if (thereIsDelayed Get-message m){
Send answer for m
}
}
if (message is Get-message) {
if (!full) {
delay(message);
} else {
full = false;
store = message.getV();
if (thereIsDelayed Put-message m){
Send answer for m
}
Seite 32
pseudo code !
get
OK
value
buffer
this.replyTo = sender; }
put
Seite 33
Seite 34
put
get
OK
value
buffer
put
OK
producer
Seite 35
get
value
consumer
Seite 36
put
get
OK
value
producer
system.shutdown();
Seite 37
buffer
consumer
So:
ept
c
c
a
Actors are not threads: they need someone that pushes themr(threads)
ved: s.
o
p
im l other
e
b
o
yt
y al
a
a
l
m
e
d
s
ueue ate now,
q
e
g
Actors aren't a replacement of threads
shared
state
pri
ro
essa aand
p
m
p
f
nt o hat are
e
m
e
Actors should beaused
for
solving
g
s t appropriate problems
M na essage
ly m
Buffers are not o
anconvincing
example for actors
Seite 39
Active buffer
def act = {
loop {
react {
case PutMsg(x) if ! full =>
data = x;
full = true;
reply()
}
}
}
}
}
}
Seite 40
ile
conc
e
r
ss to tors
e
r
g
o
c
in pr kka's a
k
r
o
A
is w 's and
e
r
e
a
Th
S cal
The code is much less complex than the Java / Akka solution
Akka version
Why:
Scala is much less verbose than Java
Condition variables (wait / notify) provide functionality
that has been transferred to conditional receive statements
loop {
react {
case PutMsg(x) if ! full =>
data = x;
full = true;
reply()
case GetMsg if full =>
full = false;
reply(data)
}
}
Reactive with
conditional receive
Seite 41
Thread-driven
Fork/Join Solution
import scala.actors.Actor
import scala.actors.Actor
Reactive style
Actions are defined not by control-statements (eventually with blocking actions), but
through their reaction on events (reception of messages).
Active and reactive components may be both part
of an application. It depends on the application to which extend.
Purely reactive actions can be implemented with high efficiency
(Thousands of them without degenerating performance)
via decoupling threads and independent actions
Summary
Linguistic features
parallel collections (e.g. Scala)
Actors (e.g. Akka, Scala)
...
Sources
Excutor-Framework / Synchronizers:
B. Goetz, J. Bloch, J. Bowbeer, D. Lea, D. Holmes, T. Peierls:
Java Concurrency in Practice
Addison-Wesley, 2006 (http://jcip.net/)
Fork/Join-Framework
Doug Lea
A Java Fork/Join Framework
http://gee.cs.oswego.edu/dl/papers/fj.pdf
Actors / Theory
Hewitt, Meijer and Szyperski:
The Actor Model (everything you wanted to know, but were afraid to ask)
http://channel9.msdn.com/Shows/Going+Deep/Hewitt-Meijer-and-Szyperski-The-Actor-Model-everything-you-wanted-to-know-but-were-afraid-to-ask
Scala
Homepage : http://www.scala-lang.org/
Akka
Homepage : http://akka.io/
Seite 45