Java concurrency - beginning                     Stetsenko Maksym                     stetsenko89@gmail.com
Lead-inObjective of concurrency - optimal utilization of system resourcesAdvantages - increases bandwidth of applicationsD...
How to create thread in java ?  1. Extends Thread:                                2. Implement Runnable  Advantages:      ...
Race conditionRace Condition is a type of flaw in an electronic or software system where the output is depend on the seque...
MonitorMonitor – its an object, which is used for mutually exclusive lock.Any object is a monitor in Java. This ability is...
Basic tools: wait, notify, notifyAllpublic final void wait() / wait(long timeout) / notify () / notifyAll () - defined in ...
Basic tools: sleep, joinDefined in Thread class:public static void sleep(long millis) - Causes the currently executing thr...
InterruptionInterruption - is a signal for the thread that it should stop an execution.Each thread has to handle his own i...
VolatileThere are several ways that can enhance performance:•    storing data in registers•    changing the order of opera...
Changing operations orderWe can not rely on operations order to avoid costs of synchronization:Example:public int currentS...
Lock starvationLock starvation occurs when a particular thread attempts to acquire a lock and never succeeds because anoth...
ReentrantLockSolves lock starvation problemConstruct a ReentrantLock object where the fairness flag is set to true.Threads...
Reader/Writer LocksReentrantReadWriteLock class.Generally, reader/writer locks are used when there are many more readers t...
ReentrantReadWriteLock example  static class RRWLC {                                                                      ...
Thread Local VariablesThread local variable:- is private to particular thread;- cannot be used to share state between thre...
Thread Local examplepublic class TestTreadLocal{    public static void main(String[] args) {        final ThreadLocal<MyOb...
Atomic operations and classesAllows operation that contains multiple instructions can be treated as atomic (for example ++...
Atomic field updatersAtomicIntegerFieldUpdater, AtomicLongFieldUpdater, AtomicReferenceFieldUpdater can help to update vol...
Implementation differences      synchronized                                  AtomicInteger                               ...
SemaphoreSemaphore is a lock with a counter.Lets different threads acquire lock one or more times.Features:         •    A...
Semaphore examplestatic class SemaphoreTester extends Thread {                                                   public cl...
BarrierThe barrier is simply a waiting point where all the threads can sync up.The last thread releases the barrier by not...
CyclicBarrier examplepublic class CyclicBarrierExample                                         private static class Summer...
Result:      Thread-0: Results for row 0 are : 1      Thread-1: Results for row 1 are : 4      Thread-2: Results for row 2...
The end
ReferencesBooks:Java Threads, Third Edition; Scott Oaks & Henry Wong; ISBN: 978-0-596-00782-9. OReilly, 2004.Concurrent Pr...
Upcoming SlideShare
Loading in …5
×

Java concurrency begining

1,387 views

Published on

Published in: Education
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,387
On SlideShare
0
From Embeds
0
Number of Embeds
10
Actions
Shares
0
Downloads
81
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Java concurrency begining

  1. 1. Java concurrency - beginning Stetsenko Maksym stetsenko89@gmail.com
  2. 2. Lead-inObjective of concurrency - optimal utilization of system resourcesAdvantages - increases bandwidth of applicationsDrawbacks - increases the complexity of the design, testing and maintenanceUsed in:  Parallel processing algorithms  Network applications, asynchronous I / O access  GUI
  3. 3. How to create thread in java ? 1. Extends Thread: 2. Implement Runnable Advantages: Advantages: - full access to functionality of the thread - Inheritance from another object is still available Disadvantages: - can not be inherited from another class , but delegation mechanism can be used alternativelyvoid run() - must be overridden in both casesvoid start() - causes this thread to begin execution; the JVM calls the run method of this thread. Can be called only once for each thread.
  4. 4. Race conditionRace Condition is a type of flaw in an electronic or software system where the output is depend on the sequence or timing of other events.Preconditions:Two or more threads are sharing the same data.At least one thread performs modification. // Thread 2:Example: int x; while (!stop) // Thread 1: { while (!stop) if (x%2 == 0) { System.out.println("x=" x++; + x); … … } } Lets assume x=0. Suppose execution of program is performed in such way: 1. if - checks x for parity in thread 2. 2. Operator «x++» increases x in thread 1. 3. System.out.println in thread 2 displays «x=1». How come ? (We have already checked x for parity ). Synchronization is needed, isnt it ? :)
  5. 5. MonitorMonitor – its an object, which is used for mutually exclusive lock.Any object is a monitor in Java. This ability is inherited from Object class.When one thread comes into synchronized block, it acquires a lock. All other threads have to wait until lock will be released.Lock can be released in such cases:- Synchronized block was successfully completed.- Exception has been thrown.Control under the monitor can be passed into other synchronized block:- in all previous cases- and when method wait has been called. (dead-clock state dangerous)note: If static block or method is synchronized, then lock of the class is acquired. Access to static fields and methods is controlled by lock of the class that is different from lock of each instance. Examples of lock acquiring: Acquiring the lock of this: Acquiring the lock of another object (lock1):public synchronized void addName() { public void addName() { public class MуClass {... synchronized(this) { private long c1 = 0;} ... private Object lock1 = new Object(); } public void inc1() { synchronized(lock1) { nameList.add("Bob"); c1++; } } }
  6. 6. Basic tools: wait, notify, notifyAllpublic final void wait() / wait(long timeout) / notify () / notifyAll () - defined in Object class let us manage the thread state:wait() – moves current thread to waiting state, releases the lock.wait(timeout) - moves current thread to waiting state for specified time. Exit will be performed either:• time elapsed;• notification is received.notify() / notifyAll() – notifies waiting thread / all waiting threads on this objects monitor that they can try to acquire the lock. Notification will be received by threads that have previously called wait. Its up to OS which thread will be resumed.note: wait() и notify(), notifyAll() must be called for acquired lock, otherwise java.lang.IllegalMonitorStateException will be thrown. Applying autoboxing and enums as locks are slippery: public class test { RESULT: static Integer foo = new Integer(1); Exception in thread "main" java.lang.IllegalMonitorStateException public static void main(String[] args) { at java.lang.Object.notifyAll(Native Method) synchronized(foo) { at test.main(test.java:6) foo++; ... foo.notifyAll(); } } }
  7. 7. Basic tools: sleep, joinDefined in Thread class:public static void sleep(long millis) - Causes the currently executing thread to sleep for the specified number of milliseconds. Method doesnt release the lock.public final void join() throws InterruptedExeption – waits for this thread to die. A lock doesnt have to be pre-acquired. public class JoinTest { public static void main(String[] args) { Thread thread = new Thread() { @Override // throw new NullPointerException(); public void run() { System.out.println( main will be join to Thread-0 Thread.currentThread().getName() + " is running"); Thread-0 is running try { Thread-0 is TERMINATED TimeUnit.SECONDS.sleep(4); main thread after join } catch (InterruptedException e) { System.out.println(e + " in " + Thread.currentThread().getName()); } // throw new NullPointerException(); } throw new NullPointerException(); }; thread.start(); main will be join to Thread-0 try { Thread-0 is running System.out.println("main will be join to " + thread.getName()); Exception in thread "Thread-0" thread.join(); java.lang.NullPointerException Thread-0 is TERMINATED } catch (InterruptedException e) { at System.out.println(e + " in main"); JoinTest$1.run(JoinTest.java:24) } main thread after join System.out.println(thread.getName() + " is " + thread.getState()); System.out.println("main thread after join");
  8. 8. InterruptionInterruption - is a signal for the thread that it should stop an execution.Each thread has to handle his own interruption.public void interrupt() - interrupts this thread.scenarios: - clears intrerrupt status, throws InterruptedException; - sets intrerrupt status; - does nothing. How to find out interrupt status? static boolean interrupted() boolean isInterrupted() clears interrupt status doesnt clear interrupt statusInterruption processing example:if (Thread.interrupted()) {// do some work if needed throw new InterruptedException();}
  9. 9. VolatileThere are several ways that can enhance performance:• storing data in registers• changing the order of operationsExample: private boolean done = false; private volatile boolean done = false;public void run( ) { Begin method run Begin method run Load register r1 with memory Label L1: while (!done) { location 0Xff12345 Test if memory location 0xff12345 == foo( ); Label L1: 1 Test if register r1 == 1 If true branch to L2 } If true branch to L2 Call method foo Call method foo Branch to L1} Branch to L1 Label L2: Label L2: End method End method runpublic void setDone( ) { done = true;} done is read only from register - done is read from main memory - there operations always will be looped is a chance to escape from loopKeyword volatile guaranties that value is never stored to registers.Synchronization has the similar effect because of registers invalidation
  10. 10. Changing operations orderWe can not rely on operations order to avoid costs of synchronization:Example:public int currentScore, totalScore, finalScorepublic void resetScore(boolean done) { finalScore = totalScore; currentScore = 0; currentScore = 0; finalScore = totalScore; totalScore += currentScore; if (done) { Thread1: Update total score Thread1: Update total score finalScore = totalScore; Thread2: See if currentScore == 0 Thread1: Set currentScore == 0 currentScore = 0; Thread2: Return -1 Thread2: See if currentScore == 0 } Thread1: Update finalScore Thread2: Return finalScore} Thread1: Set currentScore == 0 Thread1: Update finalScorepublic int getFinalScore( ) { logic is correct logic is corrupted if (currentScore == 0) return finalScore; return -1;} Synchronization protects operations from mixing:JVM cannot move operation outside the synchronization block.But operation that is located before or after synchronization block can be moved into synchronization block.
  11. 11. Lock starvationLock starvation occurs when a particular thread attempts to acquire a lock and never succeeds because another thread is already holding the lock.Reasons:The thread knows nothing about other contestants.The thread with higher priority is served first.A generous amount of threads.Synchronized blocks within loops often have this problem:while(true) { synchronized (this) { // execute some code }}
  12. 12. ReentrantLockSolves lock starvation problemConstruct a ReentrantLock object where the fairness flag is set to true.Threads are served very close to a first-come, first-served basis regardless of the threads priority.Drawbacks:The priority can be set because the developer wanted to have the scheduler behave in a certain manner. ReentrantLock may change the desired scheduling behavior. fairness false fairness trueExample: Thread-0 before sb Thread-1 before sb Thread-9 before sb Thread-2 before sbfinal ReentrantLock _lock = new ReentrantLock(true); Thread-3 before sb Thread-5 before sb Thread-7 before sb Thread-6 before sb@Override Thread-4 before sb Thread-6 in sbpublic void run() { Thread-6 before sb Thread-1 in sb System.out.println(Thread.currentThread().getName() + " before sb"); _lock.lock(); // will wait until this thread gets the lock Thread-5 before sb Thread-2 in sb try Thread-2 before sb Thread-5 in sb { Thread-1 before sb Thread-3 before sb System.out.println(Thread.currentThread().getName() + " in sb"); Thread-2 in sb Thread-3 in sb finally Thread-5 in sb Thread-7 before sb { Thread-6 in sb Thread-7 in sb //releasing the lock so that other threads can get notifies _lock.unlock(); Thread-4 in sb Thread-9 before sb } Thread-7 in sb Thread-9 in sb} Thread-3 in sb Thread-0 before sb Thread-9 in sb Thread-0 in sb Thread-0 in sb Thread-4 before sb Thread-1 in sb Thread-4 in sb
  13. 13. Reader/Writer LocksReentrantReadWriteLock class.Generally, reader/writer locks are used when there are many more readers than writers;The reader/writer lock is needed—to share data access during the long periods of time when only reading is needed.ReadLock - can be shared between readersWriteLock - exclusivework principle:preconditions: there are lots of writers and readers;behaviour (fairness = false) : Reader has finished task  Writer will be called; Writer has finished task  Reader or Writer will be called (arbitrary schedule);behaviour (fairness = true) :Threads are served as first-come, first-served basis
  14. 14. ReentrantReadWriteLock example static class RRWLC { Result: ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private final Lock read = readWriteLock.readLock(); Reader :Thread-7 is reading : sb = Reader :Thread-5 is reading : sb = private final Lock write = readWriteLock.writeLock(); Reader :Thread-0 is reading : sb = Reader :Thread-2 is reading : sb = StringBuilder sb = new StringBuilder(); Reader :Thread-3 is reading : sb = Reader :Thread-5 has finished reading Reader :Thread-3 has finished reading Reader :Thread-0 has finished reading public void read() { Reader :Thread-2 has finished reading Reader :Thread-7 has finished reading read.lock(); Writer :Thread-8 is writing Now sb = + try{ TimeUnit.SECONDS.sleep(2); //sout Writer :Thread-8 has finished writing Writer :Thread-9 is writing Now sb = + + } finally { read.unlock(); //sout } Writer :Thread-9 has finished writing Reader :Thread-1 is reading : sb = + + } Reader :Thread-4 is reading : sb = + + Reader :Thread-1 has finished reading Reader :Thread-4 has finished reading Writer :Thread-11 is writing Now sb = + + + public void write (){ Writer :Thread-11 has finished writing Reader :Thread-6 is reading : sb = + + + write.lock(); Reader :Thread-6 has finished reading Writer :Thread-10 is writing Now sb = + + + + try{ Writer :Thread-10 has finished writingSystem.out.println("Now sb = " + sb.append(" + "));//sout } finally{ write.unlock(); //sout } } } static class Reader extends Thread { static class Writer extends Thread { private RRWLC rrwlc; private RRWLC rrwlc; @Override @Override public void run() { ... rrwlc.read(); ...} public void run() { ... rrwlc.write(); ...} } }
  15. 15. Thread Local VariablesThread local variable:- is private to particular thread;- cannot be used to share state between threads;- access to the variable need never be synchronized;If TLV has never been set before the initialValue() is called to return the value. Qualities Thread Local Local Object state independency + + Common monitor exists + - Lazy initialization + - disadvantages: Perfomance loses on chosing/getting object
  16. 16. Thread Local examplepublic class TestTreadLocal{ public static void main(String[] args) { final ThreadLocal<MyObject> perThreadCounter = new ThreadLocal<MyObject>(); Thread t1 = new Thread() { Thread t2 = new Thread() { public void run() { public void run() { perThreadCounter.set(new MyObject(2)); perThreadCounter.set(new MyObject(3)); info(perThreadCounter); info(perThreadCounter); perThreadCounter.get().setX(8); perThreadCounter.get().setX(7); timeout(3); timeout(3); info(perThreadCounter); info(perThreadCounter); } } }; }; System.out.println("In main : " + perThreadCounter.get()); t1.start(); timeout(1); t2.start(); Result: } In main : null Thread-0 : java.lang.ThreadLocal@4ce86da0 : concurrency.TestTreadLocal2$MyObject@2f754ad2 : 2 Thread-1 : java.lang.ThreadLocal@4ce86da0 : concurrency.TestTreadLocal2$MyObject@95c7850 : 3 Thread-1 : java.lang.ThreadLocal@4ce86da0 : concurrency.TestTreadLocal2$MyObject@95c7850 : 7 Thread-0 : java.lang.ThreadLocal@4ce86da0 : concurrency.TestTreadLocal2$MyObject@2f754ad2 : 8
  17. 17. Atomic operations and classesAllows operation that contains multiple instructions can be treated as atomic (for example ++) ;Classes: AtomicInteger, AtomicLong, AtomicBoolean, and AtomicReference.get() and set() - provide volatile functionality.getAndSet() - sets the new value returns the previous value. compareAndSet (exp, new) compare exp with current value. if they are equal - set new value, return true. weakCompareAndSet (exp, new)The AtomicInteger and AtomicLong additional methods:incrementAndGet(), getAndIncrement() - pre/post-incrementdecrementAndGet(), getAndDecrement() - pre/post-decrementaddAndGet(), getAndAdd() - pre- and post-operators for the delta value.
  18. 18. Atomic field updatersAtomicIntegerFieldUpdater, AtomicLongFieldUpdater, AtomicReferenceFieldUpdater can help to update volatile variables.These classes are abstract. Use the static newUpdater() method.Features: • Is used as "wrappers" around a volatile field; • Dont require adding an extra object for atomic access to your class; • Let refer to the variable "normally" (without get, set);To avoid using the synchronization via the atomic classes we have to make: • Simple variable substitution; • Changing algorithms; • Retrying operations;
  19. 19. Implementation differences synchronized AtomicInteger AtomicIntegerFieldUpdaterpublic class AtomicCounter { publiclass AtomicCounter { public class AtomicIntegerFieldUpdaterExample {int value = 0; private final AtomicInteger value = new public static void main(String[] args) { AtomicInteger(0); Counter c1 = new Counter(10);public synchronized void Counter c2 = new Counter(20);increment () { public int increment () {value++; return value.incrementAndGet(); AtomicIntegerFieldUpdater<Counter> iUpdater =} } AtomicIntegerFieldUpdater.newUpdater(Counter.class, // or via compareAndSet "value"); public void increment() { iUpdater.incrementAndGet(c1); while (true) { iUpdater.incrementAndGet(c2); int current = value.get(); System.out.println("c1.value = " + iUpdater.get(c1)); int next = current + 1; System.out.println("c2.value = " + iUpdater.get(c2)); } if (integer.compareAndSet(current, next)) { static class Counter{ return; } volatile int value; // private is not allowed } } Counter(int value) { this.value = value; } } }
  20. 20. SemaphoreSemaphore is a lock with a counter.Lets different threads acquire lock one or more times.Features: • A number of simultaneously executing threads have to be set in the constructor; • The acquire() and release() are similar to the lock() and unlock() methods of the Lock; • Supply fairness politics. • There is no concept of nesting;
  21. 21. Semaphore examplestatic class SemaphoreTester extends Thread { public class SemaphoreExample { public static void main(String[] args) { private Semaphore s; SemaphoreTester(Semaphore s) { this.s = s;} Semaphore sem = new Semaphore(3); @Override SemaphoreTester st1 = new SemaphoreTester(sem); public void run() { SemaphoreTester st2 = new SemaphoreTester(sem); try { st1.start(); System.out.println(getName() + " at first : is trying to acquire the lock "); st2.start(); s.acquire(); } System.out.println(getName() + " semaphores first acquire has got"); System.out.println(getName() + " second time: is trying to acquire the lock " +TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())); s.acquire(); System.out.println(getName() + " semaphores second acquire " +TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())); TimeUnit.SECONDS.sleep(5); Result: s.release(); System.out.println(getName() + " semaphore has been released"); Thread-1 at first : is trying to acquire the lock s.release(); Thread-1 semaphores first acquire has got System.out.println(getName() + " semaphore has been released"); Thread-1 second time: is trying to acquire the lock 1351581890 } catch (InterruptedException e) { Thread-1 semaphores second acquire 1351581890 e.printStackTrace(); lates. Thread-0 at first : is trying to acquire the lock } Thread-0 semaphores first acquire has got Thread-0 second time: is trying to acquire the lock 1351581890 } Thread-1 semaphore has been released } Thread-1 semaphore has been released} Thread-0 semaphores second acquire 1351581895 Thread-0 semaphore has been released Thread-0 semaphore has been released
  22. 22. BarrierThe barrier is simply a waiting point where all the threads can sync up.The last thread releases the barrier by notifying all of the other threads. stage 1 waiting stage 2 waiting stage 3 ... stage 1 waiting stage 2 waiting stage 3 ... stage 1 waiting stage 2 waiting stage 3 ...Barrier against join()benefits:we mustnt always create new threads;logical operations can be placed together;drawbacks: complex reinitialization process;Barrier can be broken when:1. Waiting threads can be interrupted;2. Thread may break through the barrier due to a timeout condition;3. Exception could be thrown by the barrier action.
  23. 23. CyclicBarrier examplepublic class CyclicBarrierExample private static class Summer extends Thread {{ int row; private static int matrix[][] = CyclicBarrier barrier; {{ 1 }, { 2, 2 }, { 3, 3, 3 }, { 4, 4, 4, 4 }, { 5, 5, 5, 5, 5 }}; private static int results[]; Summer(CyclicBarrier barrier, int row) { this.barrier = barrier; this.row = row; } public static void main(String args[]) { public void run() { final int rows = matrix.length; int columns = matrix[row].length; results = new int[rows]; int sum = 0; Runnable merger = new Runnable(){ for (int i = 0; i < columns; i++) public void run() sum += matrix[row][i]; { int sum = 0; results[row] = sum; for (int i = 0; i < rows; i++) System.out.println(Thread.currentThread().getName() + ": sum += results[i]; Results for row " + row + " are : " + sum); System.out.println("Merger :"+ " Results are: " + sum); }}; try{ barrier.await(); // wait for others System.out.println(Thread.currentThread().getName() + CyclicBarrier barrier = new CyclicBarrier(rows, merger); " do something else " + System.currentTimeMillis()); for (int i = 0; i < rows; i++) } catch ... { new Summer(barrier, i).start(); } }
  24. 24. Result: Thread-0: Results for row 0 are : 1 Thread-1: Results for row 1 are : 4 Thread-2: Results for row 2 are : 9 Thread-4: Results for row 4 are : 25 Thread-3: Results for row 3 are : 16 Merger : Results are: 55 Thread-3 do something else 1351699717125 Thread-0 do something else 1351699717125 Thread-1 do something else 1351699717125 Thread-2 do something else 1351699717125 Thread-4 do something else 1351699717125
  25. 25. The end
  26. 26. ReferencesBooks:Java Threads, Third Edition; Scott Oaks & Henry Wong; ISBN: 978-0-596-00782-9. OReilly, 2004.Concurrent Programming in Java: Design Principles and Patterns (2nd edition) Doug Lea; ISBN 0-201-31009-0. AddisonWesley, 1999.Web recources:http://www.javamex.com/tutorials/synchronization_concurrency_7_atomic_updaters.shtmlhttp://www.baptiste-wicht.com/2010/09/java-concurrency-atomic-variables/http://www.ibm.com/developerworks/java/library/j-jtp11234/http://programmingexamples.wikidot.com/cyclicbarrierhttp://javarevisited.blogspot.com/2012/07/cyclicbarrier-example-java-5-concurrency-tutorial.htmlhttp://tutorials.jenkov.com/java-concurrency/semaphores.htmlhttp://alexbtw.livejournal.com/3355.html

×