From Runnable and synchronized To atomically() and parallel()

Post on 30-Nov-2014

2,683 views 0 download

Tags:

description

 

transcript

3 questions

2 solutions

1 problem

Multithreading

Multithreading

Multithreading

Multithreading

Parallel computing

Parallel computing

Parallel computing

Parallel computing

Parallel computing

Parallel computing

Java & API

Java & API

http://www.flickr.com/photos/jmchuff/

Multicore processors

Multicore processors

Multicore processors

On the sofware side

On the sofware side

A classical example

public class Singleton {

private static Singleton instance ;

private Singleton() {}

public static Singleton getInstance() {

if (instance == null) {

instance = new Singleton() ;

}

return instance ;

} }

A classical example

A classical example

public class Singleton {

private static Singleton instance ;

private Singleton() {}

public static Singleton getInstance() {

if (instance == null) {

instance = new Singleton() ;

}

return instance ;

} }

A classical example

A classical example

public class Singleton {

private static Singleton instance ;

private Singleton() {}

public static synchronized Singleton getInstance() {

if (instance == null) {

instance = new Singleton() ;

}

return instance ;

} }

public class Singleton {

private static Singleton instance ;

private Singleton() {}

public static synchronized Singleton getInstance() {

if (instance == null) {

instance = new Singleton() ;

}

return instance ;

} }

A classical example

public class Singleton {

private static Singleton instance ;

private Singleton() {}

public static synchronized Singleton getInstance() {

if (instance == null) {

instance = new Singleton() ;

}

return instance ;

} }

A classical example

A classical example

A classical example

public class Singleton {

private static Singleton instance ;

private Singleton() {}

public static synchronized Singleton getInstance() {

if (instance == null) {

instance = new Singleton() ;

}

return instance ;

} }

A classical example

public class Singleton {

private static Singleton instance ;

public static Singleton getInstance() {

if (instance == null) {

synchronized (Singleton.class) {

if (instance == null) {

instance = new Singleton() ;

}

}

}

return instance ;

}

}

A classical example

public class Singleton {

private static Singleton instance ;

public static Singleton getInstance() {

if (instance == null) {

synchronized (Singleton.class) {

if (instance == null) {

instance = new Singleton() ;

}

}

}

return instance ;

}

}

A classical example

public class Singleton {

private static Singleton instance ;

public static Singleton getInstance() {

if (instance == null) {

synchronized (Singleton.class) {

if (instance == null) {

instance = new Singleton() ;

}

}

}

return instance ;

}

}

A classical example

Solution to the « data race »

Solution to the « data race »

Solution to the « data race »

Solution to the « data race »

Solution to the « data race »

The JLS

The JLS

The JLS

The JLS

The JLS

The JLS

The JLS

The JLS

The JLS

The JLS

Happens before

x = 1

r1 = x

Happens before

x = 1

r1 = x

Happens before

x = 1

r1 = x

Happens before

r1 1

x = 1

r1 = x

Happens before

Happens before

Example : normal read / write

private int index ;

public void gloriousIncrementation() {

index++ ;

}

public void happyTesting() {

if (index > 10) {

System.out.println("Index is BIG!") ;

}

}

private int index ;

public void gloriousIncrementation() {

index++ ;

}

public void happyTesting() {

if (index > 10) {

System.out.println("Index is BIG!") ;

}

}

Example : normal read / write

private volatile int index ;

public void gloriousIncrementation() {

index++ ;

}

public void happyTesting() {

if (index > 10) {

System.out.println("Index is BIG!") ;

}

}

Example : volatile read / write

Problematic case

public void niceMethod() {

x = 1 ;

synchronized(lock) {

y = 1 ;

}

}

public void coolMethod() {

synchronized(lock) {

r1 = y ;

}

r2 = x ;

}

private int x, y, r1, r2 ;

private Object lock = new Object() ;

public void niceMethod() {

x = 1 ;

synchronized(lock) {

y = 1 ;

}

}

public void coolMethod() {

synchronized(lock) {

r1 = y ;

}

r2 = x ;

}

private int x, y, r1, r2 ;

private Object lock = new Object() ;

Problematic case

public void niceMethod() {

x = 1 ;

synchronized(lock) {

y = 1 ;

}

}

public void coolMethod() {

synchronized(lock) {

r1 = y ;

}

r2 = x ;

}

private int x, y, r1, r2 ;

private Object lock = new Object() ;

Problematic case

public void niceMethod() {

x = 1 ;

synchronized(lock) {

y = 1 ;

}

}

public void coolMethod() {

synchronized(lock) {

r1 = y ;

}

r2 = x ;

}

private int x, y, r1, r2 ;

private Object lock = new Object() ;

Problematic case

r1 = 1, r2 = 1

public void niceMethod() {

x = 1 ;

synchronized(lock) {

y = 1 ;

}

}

public void coolMethod() {

synchronized(lock) {

r1 = y ;

}

r2 = x ;

}

private int x, y, r1, r2 ;

private Object lock = new Object() ;

Problematic case

public void niceMethod() {

x = 1 ;

synchronized(lock) {

y = 1 ;

}

}

public void coolMethod() {

synchronized(lock) {

r1 = y ;

}

r2 = x ;

}

private int x, y, r1, r2 ;

private Object lock = new Object() ;

Problematic case

public void niceMethod() {

x = 1 ;

synchronized(lock) {

y = 1 ;

}

}

public void coolMethod() {

synchronized(lock) {

r1 = y ;

}

r2 = x ;

}

private int x, y, r1, r2 ;

private Object lock = new Object() ;

Problematic case

r1 = 0, r2 = ?

Back to the double check locking

public class Singleton {

private static Singleton instance ;

public static Singleton getInstance() {

if (instance == null) {

synchronized (Singleton.class) {

if (instance == null) {

instance = new Singleton() ;

}

}

}

return instance ;

}

}

public class Singleton {

private static Singleton instance ;

public static Singleton getInstance() {

if (instance == null) {

synchronized (Singleton.class) {

if (instance == null) {

instance = new Singleton() ;

}

}

}

return instance ;

}

}

Back to the double check locking

public class Singleton {

private static Singleton instance ;

public static Singleton getInstance() {

if (instance == null) {

synchronized (Singleton.class) {

if (instance == null) {

instance = new Singleton() ;

}

}

}

return instance ;

}

}

Back to the double check locking

public class Singleton {

private static Singleton instance ;

public static Singleton getInstance() {

if (instance == null) {

synchronized (Singleton.class) {

if (instance == null) {

instance = new Singleton() ;

}

}

}

return instance ;

}

}

Back to the double check locking

public class Singleton {

private static volatile Singleton instance ;

public static Singleton getInstance() {

if (instance == null) {

synchronized (Singleton.class) {

if (instance == null) {

instance = new Singleton() ;

}

}

}

return instance ;

}

}

Back to the double check locking

Is there an elegant solution ?

Is there an elegant solution ?

public enum Singleton {

instance ;

}

Is there an elegant solution ?

public enum Singleton {

instance ;

}

Example

private Object o = new Object() ;

private int index = 0 ;

public void slickMethod() {

synchronized (o) {

index++ ;

}

}

private Object o = new Object() ;

private int index = 0 ;

public void slickMethod() {

synchronized (o) {

index++ ;

}

}

Example

private Object o = new Object() ;

private int index = 0 ;

public void slickMethod() {

synchronized (o) {

index++ ;

}

}

Example

Memory barrier

Memory barrier

Optimization 1

Optimization 1

Optimization 1

Optimization 1

Optimization 2

Optimization 2

Cache trap !

Cache trap !

False sharing

False sharing

Variable padding

public class Sequence {

private static final AtomicLongFieldUpdater<Sequence> updater =

AtomicLongFieldUpdater.newUpdater(Sequence.class, "value");

private volatile long p1 = 7L, p2 = 7L, p3 = 7L, p4 = 7L,

p5 = 7L, p6 = 7L, p7 = 7L ;

private volatile long value = Sequencer.INITIAL_CURSOR_VALUE ;

private volatile long q1 = 7L, q2 = 7L, q3 = 7L, q4 = 7L,

q5 = 7L, q6 = 7L, q7 = 7L;

// ...

public long sumPaddingToPreventOptimisation() {

return p1 + p2 + p3 + p4 + p5 + p6 + p7 + value +

q1 + q2 + q3 + q4 + q5 + q6 + q7;

}

public void setPaddingValue(final long value) {

p1 = p2 = p3 = p4 = p5 = p6 = p7 = q1 = q2 = q3 = q4 = q5 = q6 = q7 = value;

}

}

package java.util.concurrent; /** * * @since 1.7 * @author Doug Lea */ public class ThreadLocalRandom extends Random { /** * The random seed. We can't use super.seed. */ private long rnd; // Padding to help avoid memory contention among seed updates in // different TLRs in the common case that they are located near // each other. private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; }

How to write efficient concurrent code ?

How to write efficient concurrent code ?

Runnable r = new Runnable() { public void run() { while (true) { System.out.println(« Let’s go sailing !") ; } } } ; Thread t = new Thread(r) ; t.start() ;

ExecutorService service = new ScheduledThreadPoolExecutor(10) ;

Callable<Boolean> task = new Callable<Boolean>() {

public Boolean call() throws Exception {

int i = 0 ;

while (i++ < 1000) {

System.out.println("Let’s go swimming !") ;

}

return true ;

}

};

Future<Boolean> f = service.submit(task) ;

Boolean b = f.get(100, TimeUnit.MILLISECONDS) ;

private Object o = new Object() ;

private int index = 0 ;

public void saltyMethod() {

synchronized (o) {

index++ ;

}

}

private Object o = new Object() ;

private int volatile index = 0 ;

public void pepperedMethod() {

index++ ;

}

Lock interface

private Lock lock = new ReentrantLock() ; public void crispyMethod() { lock.lock() ; // blocking call as synchronized // ... lock.unlock() ; } ;

Lock interface

private Lock lock = new ReentrantLock() ; public void crispyMethod() { lock.tryLock(10, TimeUnit.MILLISECONDS) ; // timeout // ... lock.unlock() ; } ;

Semaphore interface

private Semaphore s = new Semaphore(5) ; public void maMethode() { s.acquire() ; // blocking call as synchronized // ... s.release() ; } ;

Semaphore interface

private Semaphore s = new Semaphore(5) ; public void maMethode() { s.tryAcquire(10, TimeUnit.MILLISECONDS) ; // timeout // ... s.release() ; } ;

Semaphore interface

CountDownLatch Class

private CountDownLatch latch = new CountDownLatch() ; public void init() { db.connect() ; // slow operation latch.countDown() ; // openning of the latch } ;

public void process() { latch.await() ; // blocks until the latch is openned } ;

CyclicBarrier Class

private CyclicBarrier barrier = new CyclicBarrier(2) ;

public void processOne() { // ... barrier.await() ; // blocks until 4 calls } ;

public void processTwo() { // ... barrier.await(10, TimeUnit.MICROSECONDS) ; } ;

ReadWriteLock Interface

ReadWriteLock Interface

private ReadWriteLock rwLock = new ReentrantReadWriteLock() ;

public void aMethodThatReads() { Lock readLock = rwLock.readLock() ; readLock.lock() ; // reading... readLock.unlock() ; } ;

public void aMethodThatWrites() { Lock writeLock = rwLock.writeLock() ; writeLock.lock() ; // writing... writeLock.unlock() ; } ;

Atomic types

private AtomicInteger index = new AtomicInteger(0) ;

public void uneMethode() {

long newValue = index.incrementAndGet() ;

}

Compare and swap = CAS

Compare and swap = CAS

public final long incrementAndGet() {

for (;;) {

long current = get() ;

long next = current + 1 ;

if (compareAndSet(current, next))

return next ;

}

}

Queue & BlockingQueue interfaces

Queue & BlockingQueue interfaces

Queue & BlockingQueue interfaces

Queue & BlockingQueue interfaces

Queue & BlockingQueue interfaces

add(e) offer(e) put(e) offer(e, time, unit)

remove() poll() take() poll(e, time, unit)

element() peek() - -

CopyOnWriteArrayList

CopyOnWriteArrayList

Immutability

Immutability

Immutability

Try trees

Immutable systems

In databases…

begin

update ... set ... where ...

commit

In databases…

begin

update ... set ... where ...

commit

In databases…

In databases…

STM Pattern

<dependency>

<groupId>se.scalablesolutions.akka</groupId>

<artifactId>akka-kernel</artifactId>

<version>1.3.1</version>

</dependency>

<repository>

<id>Akka</id>

<name>Akka Maven2 Repository</name>

<url>http://akka.io/repository/</url>

</repository>

STM Pattern

final Ref<Integer> source = new Ref<Integer>(500) ;

final Atomic<Object> atom = new Atomic<Object>() {

@Override

public Object atomically() {

source.swap(source.get() + 1) ;

return null ;

}

} ;

atom.execute() ;

STM Pattern

final Ref<Integer> source = new Ref<Integer>(500) ;

final Atomic<Object> atom = new Atomic<Object>() {

@Override

public Object atomically() {

source.swap(source.get() + 1) ;

return null ;

}

} ;

atom.execute() ;

STM Pattern

final Ref<Integer> source = new Ref<Integer>(500) ;

final Atomic<Object> atom = new Atomic<Object>() {

@Override

public Object atomically() {

source.swap(source.get() + 1) ;

return null ;

}

} ;

atom.execute() ;

STM Pattern

STM Pattern

STM Pattern

List<E> queue1 = new ... ;

List<E> queue2 = new ... ;

final Ref<List<E>> refQueue1 =

new Ref<List<E>>(Collections.unmodifiableList(queue1)) ;

final Ref<List<E>> refQueue2 =

new Ref<List<E>>(Collections.unmodifiableList(queue2)) ;

final Atomic<Object> atom = new Atomic<Object>() {

@Override

public Object atomically() {

// duplication

List<E> dupQ1 = new ArrayList<>(refQueue1) ;

List<E> dupQ2 = new ArrayList<>(refQueue2) ;

// transfer

E element = duqQ1.remove(...) ;

duqQ2.add(element) ;

// swapping

refQueue1.swap(Collections.unmodifiableList(dupQ1) ;

refQueue2.swap(Collections.unmodifiableList(dupQ2) ;

}

} ;

STM : implementation

STM : implementation

STM : why is it so important ?

STM : why is it so important ?

STM : why is it so important ?

STM : why is it so important ?

STM : why is it so important ?

STM : why is it so important ?

STM : why is it so important ?

Actors

Actors

Akka Actors

Akka Actors

Akka Actors

public class Vador extends UntypedActor {

public void onReceive(Object o) throws Exception {

// o is the message

// return something ;

getContext().reply(something) ;

}

}

Akka Actors

public static void main(String[] args) {

Message message = new Message() ;

ActorRef jeff =

Actors.actorOf(Vader.class).start() ;

Future future =

jeff.sendRequestReplyFuture(message) ;

// a bit further away

// beware, it’s not our good ol’ concurrent Future

result = future.get() ;

}

Akka Actors

public class PrimeFinderActor extends UntypedActor {

public void onReceive(Object o) throws Exception {

List<Integer> bounds = (List<Integer>)o ;

int debut = bounds.get(0) ;

int fin = bounds.get(1) ;

PrimeFactors pfs = new PrimeFactors() ;

for (int i = start ; i < end ; i++) {

PrimeFactors pfi = pfs.getPrimeFactors(i) ;

pfs.add(pfi) ;

}

// return pfs ;

getContext().reply(pfs) ;

}

}

public class PrimeFactorCallable implements Callable<PrimeFactors> {

private int debut, fin ;

public PrimeFactorCallable(int debut, int fin) {

this.debut = debut ; this.fin = fin ;

}

public PrimeFactors call() throws Exception {

PrimeFactors pfs = new PrimeFactors() ;

for (int i = debut ; i < fin ; i++) {

PrimeFactors pfi = pfs.getPrimeFactors(i) ;

pfs.add(pfi) ;

}

return pfs ;

}

}

public static void main(String[] args) {

Future [] futures = new Future [400] ; // it’s the Akka Future

for (int i = 0 ; i < futures.length ; i++) {

List<Integer> bound = Collections.unmodifiableList(

Arrays.asList(10*i, 10*(i + 1))) ;

ActorRef primeFactorFinder =

Actors.actorOf(PrimeFinderActor.class).start() ;

futures[i] = primeFactorFinder.sendRequestReplyFuture(bound) ;

}

PrimeFactors pfs = new PrimeFactors() ;

for (int i = 0 ; i < futures.length ; i++) {

pfs.add((PrimeFactors)futures[i].get()) ;

}

Actors.registry().shutdownAll() ;

}

public static void main(String... args)

throws ExecutionException, InterruptedException {

ExecutorService es = new ScheduledThreadPoolExecutor(10) ;

Future [] futures = new Future [400] ;

for (int i = 0 ; i < futures.length ; i++) {

PrimeFactorCallable callable =

new PrimeFactorCallable(10*i, 10*(i + 1)) ;

futures[i] = es.submit(callable) ;

}

PrimeFactors pfs = new PrimeFactors() ;

for (int i = 0 ; i < futures.length ; i++) {

pfs.add((PrimeFactors)futures[i].get()) ;

}

es.shutdown() ;

}

BTW, the result is…

[2^3989][3^1996][5^996][7^664][11^399][13^331][17^248][19^221][23^180][29^141][31^133][37^110][41^99][43^95][47^86][53^76][59^68][61^66][67^59]

[71^56][73^54][79^50][83^48][89^44][97^41][101^39][103^38][107^37][109^36][113^35][127^31][131^30][137^29][139^28][149^26][151^26][157^25][163^

24][167^23][173^23][179^22][181^22][191^20][193^20][197^20][199^20][211^18][223^17][227^17][229^17][233^17][239^16][241^16][251^15][257^15][263

^15][269^14][271^14][277^14][281^14][283^14][293^13][307^13][311^12][313^12][317^12][331^12][337^11][347^11][349^11][353^11][359^11][367^10][37

3^10][379^10][383^10][389^10][397^10][401^9][409^9][419^9][421^9][431^9][433^9][439^9][443^9][449^8][457^8][461^8][463^8][467^8][479^8][487^8][

491^8][499^8][503^7][509^7][521^7][523^7][541^7][547^7][557^7][563^7][569^7][571^7][577^6][587^6][593^6][599^6][601^6][607^6][613^6][617^6][619

^6][631^6][641^6][643^6][647^6][653^6][659^6][661^6][673^5][677^5][683^5][691^5][701^5][709^5][719^5][727^5][733^5][739^5][743^5][751^5][757^5]

[761^5][769^5][773^5][787^5][797^5][809^4][811^4][821^4][823^4][827^4][829^4][839^4][853^4][857^4][859^4][863^4][877^4][881^4][883^4][887^4][90

7^4][911^4][919^4][929^4][937^4][941^4][947^4][953^4][967^4][971^4][977^4][983^4][991^4][997^4][1009^3][1013^3][1019^3][1021^3][1031^3][1033^3]

[1039^3][1049^3][1051^3][1061^3][1063^3][1069^3][1087^3][1091^3][1093^3][1097^3][1103^3][1109^3][1117^3][1123^3][1129^3][1151^3][1153^3][1163^3

][1171^3][1181^3][1187^3][1193^3][1201^3][1213^3][1217^3][1223^3][1229^3][1231^3][1237^3][1249^3][1259^3][1277^3][1279^3][1283^3][1289^3][1291^

3][1297^3][1301^3][1303^3][1307^3][1319^3][1321^3][1327^3][1361^2][1367^2][1373^2][1381^2][1399^2][1409^2][1423^2][1427^2][1429^2][1433^2][1439

^2][1447^2][1451^2][1453^2][1459^2][1471^2][1481^2][1483^2][1487^2][1489^2][1493^2][1499^2][1511^2][1523^2][1531^2][1543^2][1549^2][1553^2][155

9^2][1567^2][1571^2][1579^2][1583^2][1597^2][1601^2][1607^2][1609^2][1613^2][1619^2][1621^2][1627^2][1637^2][1657^2][1663^2][1667^2][1669^2][16

93^2][1697^2][1699^2][1709^2][1721^2][1723^2][1733^2][1741^2][1747^2][1753^2][1759^2][1777^2][1783^2][1787^2][1789^2][1801^2][1811^2][1823^2][1

831^2][1847^2][1861^2][1867^2][1871^2][1873^2][1877^2][1879^2][1889^2][1901^2][1907^2][1913^2][1931^2][1933^2][1949^2][1951^2][1973^2][1979^2][

1987^2][1993^2][1997^2][1999^2][2003^1][2011^1][2017^1][2027^1][2029^1][2039^1][2053^1][2063^1][2069^1][2081^1][2083^1][2087^1][2089^1][2099^1]

[2111^1][2113^1][2129^1][2131^1][2137^1][2141^1][2143^1][2153^1][2161^1][2179^1][2203^1][2207^1][2213^1][2221^1][2237^1][2239^1][2243^1][2251^1

][2267^1][2269^1][2273^1][2281^1][2287^1][2293^1][2297^1][2309^1][2311^1][2333^1][2339^1][2341^1][2347^1][2351^1][2357^1][2371^1][2377^1][2381^

1][2383^1][2389^1][2393^1][2399^1][2411^1][2417^1][2423^1][2437^1][2441^1][2447^1][2459^1][2467^1][2473^1][2477^1][2503^1][2521^1][2531^1][2539

^1][2543^1][2549^1][2551^1][2557^1][2579^1][2591^1][2593^1][2609^1][2617^1][2621^1][2633^1][2647^1][2657^1][2659^1][2663^1][2671^1][2677^1][268

3^1][2687^1][2689^1][2693^1][2699^1][2707^1][2711^1][2713^1][2719^1][2729^1][2731^1][2741^1][2749^1][2753^1][2767^1][2777^1][2789^1][2791^1][27

97^1][2801^1][2803^1][2819^1][2833^1][2837^1][2843^1][2851^1][2857^1][2861^1][2879^1][2887^1][2897^1][2903^1][2909^1][2917^1][2927^1][2939^1][2

953^1][2957^1][2963^1][2969^1][2971^1][2999^1][3001^1][3011^1][3019^1][3023^1][3037^1][3041^1][3049^1][3061^1][3067^1][3079^1][3083^1][3089^1][

3109^1][3119^1][3121^1][3137^1][3163^1][3167^1][3169^1][3181^1][3187^1][3191^1][3203^1][3209^1][3217^1][3221^1][3229^1][3251^1][3253^1][3257^1]

[3259^1][3271^1][3299^1][3301^1][3307^1][3313^1][3319^1][3323^1][3329^1][3331^1][3343^1][3347^1][3359^1][3361^1][3371^1][3373^1][3389^1][3391^1

][3407^1][3413^1][3433^1][3449^1][3457^1][3461^1][3463^1][3467^1][3469^1][3491^1][3499^1][3511^1][3517^1][3527^1][3529^1][3533^1][3539^1][3541^

1][3547^1][3557^1][3559^1][3571^1][3581^1][3583^1][3593^1][3607^1][3613^1][3617^1][3623^1][3631^1][3637^1][3643^1][3659^1][3671^1][3673^1][3677

^1][3691^1][3697^1][3701^1][3709^1][3719^1][3727^1][3733^1][3739^1][3761^1][3767^1][3769^1][3779^1][3793^1][3797^1][3803^1][3821^1][3823^1][383

3^1][3847^1][3851^1][3853^1][3863^1][3877^1][3881^1][3889^1][3907^1][3911^1][3917^1][3919^1][3923^1][3929^1][3931^1][3943^1][3947^1][3967^1][39

89^1]

Akka Actors

Akka Actors + STM

Akka Actors + STM

public class Balance {

public final int amount ;

public Balance(int amount) {

this.amount = amount ;

}

}

public class Deposit {

public final int amount ;

public Deposit(int amount) {

this.amount = amount ;

}

}

public class Withdrawal {

public final int amount ;

public Balance(int amount) {

this.amount = amount ;

}

}

public class GetBalance {

}

public class BankAccount extends UntypedTransactor {

private final Ref<Integer> balance = new Ref<Integer>(0) ;

public void atomically(final Object message) {

if (message instanceof Deposit) {

int amount = ((Deposit)message).amount ;

if (amount > 0)

balance.swap(balance.get() + amount) ;

}

if (message instanceof Withdrawal) {

int amount = ((Retrait)message).amount ;

if (amount > 0) {

if (balance.get() < amount) throw new IllegalStateException("...") ;

balance.swap(balance.get() - amount) ;

}

}

if (message instanceof GetBalance)

getContext().replySafe((new Balance(balance.get()))) ;

}

}

public class BankAccount extends UntypedTransactor {

private final Ref<Integer> balance = new Ref<Integer>(0) ;

public void atomically(final Object message) {

if (message instanceof Deposit) {

int amount = ((Deposit)message).amount ;

if (amount > 0)

balance.swap(balance.get() + amount) ;

}

if (message instanceof Withdrawal) {

int amount = ((Retrait)message).amount ;

if (amount > 0) {

if (balance.get() < amount) throw new IllegalStateException("...") ;

balance.swap(balance.get() - amount) ;

}

}

if (message instanceof GetBalance)

getContext().replySafe((new Balance(balance.get()))) ;

}

}

public class BankAccount extends UntypedTransactor {

private final Ref<Integer> balance = new Ref<Integer>(0) ;

public void atomically(final Object message) {

if (message instanceof Deposit) {

int amount = ((Deposit)message).amount ;

if (amount > 0)

balance.swap(balance.get() + amount) ;

}

if (message instanceof Withdrawal) {

int amount = ((Retrait)message).amount ;

if (amount > 0) {

if (balance.get() < amount) throw new IllegalStateException("...") ;

balance.swap(balance.get() - amount) ;

}

}

if (message instanceof GetBalance)

getContext().replySafe((new Balance(balance.get()))) ;

}

}

public class BankAccount extends UntypedTransactor {

private final Ref<Integer> balance = new Ref<Integer>(0) ;

public void atomically(final Object message) {

if (message instanceof Deposit) {

int amount = ((Deposit)message).amount ;

if (amount > 0)

balance.swap(balance.get() + amount) ;

}

if (message instanceof Withdrawal) {

int amount = ((Retrait)message).amount ;

if (amount > 0) {

if (balance.get() < amount) throw new IllegalStateException("...") ;

balance.swap(balance.get() - amount) ;

}

}

if (message instanceof GetBalance)

getContext().replySafe((new Balance(balance.get()))) ;

}

}

public class Transfer {

public final ActorRef source ;

public final ActorRef destination ;

public final int amount ;

public Transfert(

final ActorRef source,

final ActorRef destination,

final int amount) {

this.source = source ;

this.destination = destination ;

this.amount = amount ;

}

}

public class BankService extends UntypedTransactor {

public Set<SendTo> coordinate(final Object message) {

if (message instanceof Transfer) {

Set<SendTo> s = new HashSet<SendTo>() ;

Transfer t = (Transfer)message ;

if (t.amount > 0) { // validation

s.add(sendTo(t.destination, new Deposit(t.amount))) ;

s.add(sendTo(t.source, new Withdrawal(t.amount))) ;

return Collections.unmodifiableSet(s) ;

}

}

return nobody() ;

}

}

public class BankService extends UntypedTransactor {

public Set<SendTo> coordinate(final Object message) {

if (message instanceof Transfer) {

Set<SendTo> s = new HashSet<SendTo>() ;

Transfer t = (Transfer)message ;

if (t.amount > 0) { // validation

s.add(sendTo(t.destination, new Deposit(t.amount))) ;

s.add(sendTo(t.source, new Withdrawal(t.amount))) ;

return Collections.unmodifiableSet(s) ;

}

}

return nobody() ;

}

}

public class BankService extends UntypedTransactor {

public Set<SendTo> coordinate(final Object message) {

if (message instanceof Transfer) {

Set<SendTo> s = new HashSet<SendTo>() ;

Transfer t = (Transfer)message ;

if (t.amount > 0) { // validation

s.add(sendTo(t.destination, new Deposit(t.amount))) ;

s.add(sendTo(t.source, new Withdrawal(t.amount))) ;

return Collections.unmodifiableSet(s) ;

}

}

return nobody() ;

}

}

public class BankService extends UntypedTransactor {

public Set<SendTo> coordinate(final Object message) {

if (message instanceof Transfer) {

Set<SendTo> s = new HashSet<SendTo>() ;

Transfer t = (Transfer)message ;

if (t.amount > 0) { // validation

s.add(sendTo(t.destination, new Deposit(t.amount))) ;

s.add(sendTo(t.source, new Withdrawal(t.amount))) ;

return Collections.unmodifiableSet(s) ;

}

}

return nobody() ;

}

}

public class BankService extends UntypedTransactor {

public Set<SendTo> coordinate(final Object message) {

if (message instanceof Transfer) {

Set<SendTo> s = new HashSet<SendTo>() ;

Transfer t = (Transfer)message ;

if (t.amount > 0) { // validation

s.add(sendTo(t.destination, new Deposit(t.amount))) ;

s.add(sendTo(t.source, new Withdrawal(t.amount))) ;

return Collections.unmodifiableSet(s) ;

}

}

return nobody() ;

}

}

Akka actors + STM

Akka actors + STM

Parallel computing in Java

Parallel computing in Java

Parallel computing in Java

Fork / Join

Fork / Join

Fork / Join : patterns

ForkJoinPool pool = new ForkJoinPool() ;

PrimeFactorsFinderRecursiveTask task = new PrimeFactorsFinderRecursiveTask(1, 4000) ; ForkJoinTask<PrimeFactors> pfsTask = pool.submit(task) ; PrimeFactors pfs = pfsTask.get() ;

public class PrimeFactorsFinderRecursiveTask extends RecursiveTask<PrimeFactors> {

private int start, end ;

protected PrimeFactors compute() {

PrimeFactors pfs = new PrimeFactors() ;

if (end - start > ITERATIONS) { // I’m too big

// processing

ForkJoinTask<PrimeFactors> task = ... ;

task.fork() ;

PrimeFactors pfs = task.get() ;

...

} else {

for (int i = start ; i < end ; i++) {

PrimeFactors pfi = pfs.getPrimeFactors(i) ;

pfs.add(pfi) ;

}

}

return pfs ;

}

}

public class PrimeFactorsFinderRecursiveTask extends RecursiveTask<PrimeFactors> {

private int start, end ;

protected PrimeFactors compute() {

PrimeFactors pfs = new PrimeFactors() ;

if (end - start > ITERATIONS) { // I’m too big

// processing

ForkJoinTask<PrimeFactors> task = ... ;

task.fork() ;

PrimeFactors pfs = task.get() ;

...

} else {

for (int i = start ; i < end ; i++) {

PrimeFactors pfi = pfs.getPrimeFactors(i) ;

pfs.add(pfi) ;

}

}

return pfs ;

}

}

public class PrimeFactorsFinderRecursiveTask extends RecursiveTask<PrimeFactors> {

private int start, end ;

protected PrimeFactors compute() {

PrimeFactors pfs = new PrimeFactors() ;

if (end - start > ITERATIONS) { // I’m too big

// processing

ForkJoinTask<PrimeFactors> task = ... ;

task.fork() ;

PrimeFactors pfs = task.get() ;

...

} else {

for (int i = start ; i < end ; i++) {

PrimeFactors pfi = pfs.getPrimeFactors(i) ;

pfs.add(pfi) ;

}

}

return pfs ;

}

}

Fork / Join : patterns

Fork / Join : patterns

// 1st strategy

if (end - start > MAX_ITERATIONS) { // I’m too big

int m = (start + end) / 2 ;

PrimeFactorsFinderTask task1 = new PrimeFactorsFinderTask(start, m) ;

PrimeFactorsFinderTask task2 = new PrimeFactorsFinderTask(m, end) ;

task1.fork() ;

task2.fork() ;

PrimeFactors pfs1 = task1.join() ;

PrimeFactors pfs2 = task2.join() ;

pfs.add(pfs1) ;

pfs.add(pfs2) ;

}

// 2nd strategy

if (end - start > MAX_ITERATIONS) { // I’m too big

List<ForkJoinTask<PrimeFactors>> pfsList = new ArrayList<ForkJoinTask<PrimeFactors>>() ; for (int i = start ; i < end – MAX_ITERATIONS ; i += MAX_ITERATIONS) { PrimeFactorsFinderRecursiveTask task = new PrimeFactorsFinderRecursiveTask(i, i + MAX_ITERATIONS) ; task.fork() ; pfsList.add(task) ; } for (ForkJoinTask<PrimeFactors> task : pfsList) { PrimeFactors pfsElement = task.join() ; pfs.add(pfsElement) ; } }

Parallel Arrays

Parallel Arrays : patterns

ForkJoinPool pool = new ForkJoinPool() ; // package !

ParralelLongArray a = ParralelLongArray.create(size, pool) ;

Parallel Arrays : patterns

a.replaceWithGeneratedValue(new LongGenerator() {

@Override

public long op() {

return rand.nextInt(100) ;

}

}) ;

Parallel Arrays : patterns

Ops.LongPredicate filter = new Ops.LongPredicate() {

@Override

public boolean op(long l1) {

return l1 > 50 ;

}

}

a2 = a.withFilter(filter) ;

a2.all() ;

Parallel Arrays : patterns

Ops.LongReducer reducer = new Ops.LongReducer() {

@Override

public long op(long l1, long l2) {

return l1 + l2 ;

}

}

long reducedValue = a.reduce(reducer, 0L) ;

Parallel Arrays : patterns

Ops.LongOp add2 = new Ops.LongOp() {

@Override

public long op(long l1) {

return l1 + 2 ;

}

} ;

a2 = a.withMapping(add2) ;

Parallel Arrays : patterns

Ops.BinaryLongOp multAB = new Ops.BinaryLongOp() {

@Override

public long op(long l1, long l2) {

return l1*l2 ;

}

} ;

a2 = a0.withMapping(multAB, a1) ;

Parallel Arrays : patterns

Ops.LongReducer sum = new Ops.LongReducer() {

@Override

public long op(long l1, long l2) {

return l1 + l2 ;

}

} ;

long normSquare = a0.withMapping(multAB, a0).reduce(sum, 0L) ;

double norm = Math.sqrt(normSquare) ;

Parallel Arrays : patterns

Java 8 Sept. 2013

What are the l ?

Collection<Person> persons = ... ;

int maxAge = persons.map(p -> p.getAge()).reduce(0, Integer::max) ;

What are the l ?

Collection<Person> persons = ... ;

int maxAge = persons.map(p -> p.getAge()).reduce(0, Integer::max) ;

Collection<Person> oldies =

persons.filter(p -> p.age > 40).into(new ArrayList()) ;

What are the l ?

Collection<Person> persons = ... ;

int maxAge = persons.map(p -> p.getAge()).reduce(0, Integer::max) ;

Collection<Person> oldies =

persons.filter(p -> p.age > 40).into(new ArrayList()) ;

What are the l ?

Collection<Person> persons = ... ;

int maxAge = persons.map(p -> p.getAge()).reduce(0, Integer::max) ;

Collection<Person> oldies =

persons.filter(p -> p.age > 40).into(new ArrayList()) ;

The new Collection interface

public interface Collection<E> {

public boolean add(E e) ;

public boolean addAll(Collection<? extends E> c) ;

// the usual methods of the Collection interface

// the new stuff

public void sort(Comparator<? super E> comparator)

default Collections.sort(comparator) ;

}

Supports parallel() !

Collection<Person> persons = ... ;

int maxAge = persons.parallel().map(p -> p.getAge()).reduce(0, Integer::max) ;

Collection<Person> oldies =

persons.parallel().filter(p -> p.age > 40).into(new ArrayList()) ;

Spliterable Interface

public interface Spliterable<E> extends Iterable<E> {

public Iterable<E>[] splits() ;

public Iterable<E>[] splits(

int maxSplits, int minPerSplits, int maxPerSplits) ;

public int naturalSplits() ;

}

Going parallel with the JDK 8

An anecdot

An anecdot

An anecdot

An anecdot

An anecdot

An anecdot

An anecdot

Algorithms

Algorithms

Algorithms

Conclusions

Conclusions

Conclusions

Conclusions

Conclusions

Conclusions

Thank you !

Q&A