Java 8 - Stamped Lock

34
ilJUG Java 8 Launch Event #2 Stamped Locks Haim Yadid - Performize-IT

description

This talk was given in ilJUG on the 29th of July 2014 and discusses the new Java8 StampedLock class. It compares it to different locking mechanism is Java and shows some insights deduced from a simple benchmark

Transcript of Java 8 - Stamped Lock

Page 1: Java 8 - Stamped Lock

ilJUG  Java  8  Launch  Event  #2  Stamped  Locks    

                               !

Haim Yadid - Performize-IT

Page 2: Java 8 - Stamped Lock

About  Me:  Haim  Yadid

•21 Years of SW development experience •Performance Expert •Consulting R&D Groups •Training: Java Performance Optimization •Organizing : ILJUG

Page 3: Java 8 - Stamped Lock

IL  JUG

•Israeli Java User Group •Reborn at 1/14 •Meetup : http://www.meetup.com/IL-JUG •G+: https://plus.google.com/u/0/communities/110138558454900054301

•Twitter: @il_jug

Page 4: Java 8 - Stamped Lock

Synchronization

Synchronized keyword was introduced to the java language from the beginning Acquire the lock on any java object

By default locking object instance on instance methods Locking the class on static methods

© Copyright Performize IT LTD.

synchronized void foo(){ do something(); }

private Object x = new Object(); void bar() { synchronized (x) { do something; } }

Page 5: Java 8 - Stamped Lock

Volatile keyword

Insures access atomicity Visibility and order

© Copyright Performize-IT LTD.CPU Profiling: Lock Contention

private volatile long counter;

public long getCounter() { return counter; }

public void increment(long amount){ ++counter; }

Page 6: Java 8 - Stamped Lock

Contention

•Two threads are considered to be contended when they try to access same lock on the same time •Locking mechanism behaves differently under contention • Contention degrades performance dramatically

Page 7: Java 8 - Stamped Lock

ReentrantLock

Introduced in Java5 Part of the java.util.concurrent package Enhanced flexibility In Java 5 had better performance (fixed by now)

© Copyright Performize IT LTD.

private final ReentrantLock lock = new ReentrantLock(); // ... public void m() { lock.lock(); // block until condition holds try { // ... method body } finally { lock.unlock() } }

Page 8: Java 8 - Stamped Lock

ReadWriteLock

Introduced in Java5 Part of the java.util.concurrent package Two locks work together inside the same lock Any amount of readers can work concurrently Write locks are taken exclusively

© Copyright Performize IT LTD.

public void increment(long amount) { try { rwlock.writeLock().lock(); counter+=amount; } finally { rwlock.writeLock().unlock(); } }

public long getCounter() { try { rwlock.readLock().lock(); return counter; } finally { rwlock.readLock().unlock(); } }

Page 9: Java 8 - Stamped Lock

Introduce Fairness

Reentrant locks can work in fair and non fair mode. Fair mode means that requests to the lock object are accepted by the order they have been received. Prevents starvation Predictable latency Much slower

© Copyright Performize IT LTD.

private final ReentrantLock lock = new ReentrantLock(true);

Page 10: Java 8 - Stamped Lock

Deadlocks

A Deadlock is a severe problem in a Java program It is a non recoverable situation requires JVM restart A cycle of locks held by different thread where each one is waiting another thread to release a lock.

© Copyright Performize-IT LTD.CPU Profiling: Concurrency problems

Thread A

Lock X

Wait on Y

Thread B

Lock Y

Wait on X

Page 11: Java 8 - Stamped Lock

tryLock

With synchronized keyword you are not able to control how much to wait Reetrantlock introduces

tryLock() – If lock already taken return false tryLock(timeout,timeunit) – Waits for a certain amount of time

Can be a solution to deadlocks

© Copyright Performize-IT LTD.CPU Profiling: Lock Contention

Page 12: Java 8 - Stamped Lock

CAS

Other approaches use low level construct such as compare and swap Faster than synchronized Limited in functionality Can be used to develop complicated mechanism

© Copyright Performize-IT LTD.CPU Profiling: Lock Contention

private final AtomicLong atomic = new AtomicLong();

public void increment(long amount) { atomic.addAndGet(amount); }

public long getCounter() { return atomic.get(); }

Page 13: Java 8 - Stamped Lock

J8 - LongAdder

Added to J8 - should be faster on multi threaded environment compared to AtomicLong Also a version for DoubleAdder

© Copyright Performize-IT LTD.CPU Profiling: Lock Contention

LongAdder adder = new LongAdder();

public void increment(long amount) { adder.add(amount); }

public long getCounter() { return adder.longValue(); }

Page 14: Java 8 - Stamped Lock

J8 - LongAdder Benchmark

Taken from http://minddotout.wordpress.com/2013/05/11/java-8-concurrency-longadder/

© Copyright Performize-IT LTD.CPU Profiling: Lock Contention

Page 15: Java 8 - Stamped Lock

Stamped  Locks                                

Page 16: Java 8 - Stamped Lock

Pessimistic

Can work the same as read write lock Assumes contention Get a stamp from

© Copyright Performize IT LTD.

long stamp = rwlock.writeLock(); try { counter+= amount; } finally { rwlock.unlockWrite(stamp); }

long stamp = rwlock.readLock(); try { result = counter; } finally { rwlock.unlockRead(stamp); } return result;

Page 17: Java 8 - Stamped Lock

Optimistic Approach

Optimistic Mechanism Try perform read if disturbed retry

© Copyright Performize-IT LTD.CPU Profiling: Lock Contention

private StampedLock rwlock = new StampedLock(); !long stamp = rwlock.tryOptimisticRead(); result = counter; !if (rwlock.validate(stamp)) { return result; }

Page 18: Java 8 - Stamped Lock

Retry

If failed one can retry

© Copyright Performize-IT LTD.CPU Profiling: Lock Contention

for (i=0;i<maxRetries;i++) { long stamp = rwlock.tryOptimisticRead(); result = counter; if (rwlock.validate(stamp)) { return result; } }

Page 19: Java 8 - Stamped Lock

Micro Benchmark

Original version developed by Tal Weiss (Takipi) https://github.com/takipi/counters-benchmark.git

Modified benchmark here https://github.com/lifey/counters-benchmark.git

The two benchmarks are very different and yield different results ( mine is better :) )

© Copyright Performize IT LTD.

Page 20: Java 8 - Stamped Lock

Disclaimer

Beware of micro benchmarks. Benchmarks can be flawed. Including this one Under different conditions they may behave differently They prove nothing for real life application Benchmark your real life applications as well Saying that benchmark contains:

Warmup Average on 10 iterations after warmup

© Copyright Performize IT LTD.

Page 21: Java 8 - Stamped Lock

ReaderWriter

A class which with configurable probability either increases a counter Reads its value

A single iteration performs it for 200M times Number of threads is configurable

© Copyright Performize IT LTD.

Page 22: Java 8 - Stamped Lock

ReaderWriter

© Copyright Performize IT LTD.

if ((innerCounter % modulo) != 0) { // read long count = counter.getCounter();! if (count > Main.TARGET_NUMBER) { Main.publish(System.currentTimeMillis()); break; } } else { // write counter.increment(modulo);}innerCounter++;

Page 23: Java 8 - Stamped Lock

Different Implementations

Volatile - using volatile keyword Atomic - AtomicLong Adder - LongAdder Synchronized Stamped (0,1,3,5 optimistic attempts) RW lock Fair RW lock

© Copyright Performize IT LTD.

Page 24: Java 8 - Stamped Lock

Results 1/2 writes - 1 thread

© Copyright Performize IT LTD.

0

1750

3500

5250

7000

Vola

tile

Ato

mic

Add

er

Sync

RWLo

ck

Stam

ped0

Stam

ped1

Stam

ped3

Stam

ped5

Page 25: Java 8 - Stamped Lock

Results 1/2 writes

© Copyright Performize IT LTD.

Valu

e A

xis

0

20000

40000

60000

80000Vo

latil

e

Ato

mic

Add

er

Sync

RWLo

ck

Stam

ped0

Stam

ped1

Stam

ped3

Stam

ped5

1 2 3 4

Page 26: Java 8 - Stamped Lock

Results (1/10 writes) - single thread

© Copyright Performize IT LTD.

0

2250

4500

6750

9000

Vola

tile

Ato

mic

Add

er

Sync

RWLo

ck

Stam

ped0

Stam

ped1

Stam

ped3

Stam

ped5

Page 27: Java 8 - Stamped Lock

Results (1/10 writes)

© Copyright Performize IT LTD.

0

25000

50000

75000

100000

Vola

tile

Ato

mic

Add

er

Sync

RWLo

ck

Stam

ped0

Stam

ped1

Stam

ped3

Stam

ped5

Page 28: Java 8 - Stamped Lock

Results 1/100 writes

© Copyright Performize IT LTD.

0

10000

20000

30000

40000

Vola

tile

Ato

mic

Add

er

Sync

RWLo

ck

Stam

ped0

Stam

ped1

Stam

ped3

Stam

ped5

Page 29: Java 8 - Stamped Lock

Results 1/100 writes

© Copyright Performize IT LTD.

0

4000

8000

12000

16000

Vola

tile

Ato

mic

Add

er

Sync

Stam

ped1

Stam

ped3

Stam

ped5

Page 30: Java 8 - Stamped Lock

Insights

RWlocks really suck under high contention. StampedLocks require at least one optimistic try. When update probability goes down more than one retry may be beneficial RWLock.tryLock is similar to lock Under low write rate StampedLock with retries can get close to atomic/volatile Fair locks are x100 slower than non fair locks under extreme cases

© Copyright Performize IT LTD.

Page 31: Java 8 - Stamped Lock

Additional Reading - LongAddr

http://minddotout.wordpress.com/2013/05/11/java-8-concurrency-longadder/ http://blog.palominolabs.com/2014/02/10/java-8-performance-improvements-longadder-vs-atomiclong/ http://psy-lob-saw.blogspot.co.il/2013/05/using-jmh-to-benchmark-multi-threaded.html?m=1 http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/LongAdder.html

© Copyright Performize IT LTD.

Page 32: Java 8 - Stamped Lock

Additional Reading - StampedLock

http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/StampedLock.html http://www.takipiblog.com/2014/05/30/java-8-stampedlocks-vs-readwritelocks-and-synchronized/ http://www.javaspecialists.eu/archive/Issue215.html

© Copyright Performize IT LTD.

Page 33: Java 8 - Stamped Lock
Page 34: Java 8 - Stamped Lock

Thanks + Q&A + Contact Me

© Copyright Performize-IT LTD.

http://il.linkedin.com/in/haimyadid

[email protected]

www.performize-it.com

blog.performize-it.com

https://github.com/lifey

@lifeyx