ca670 - concurrent programmingdavids/courses/ca670... · java threadssynchronisationmulticore ca670...

26
Java Threads Synchronisation Multicore CA670 - Concurrent Programming Java Threads David Sinclair Java Threads Synchronisation Multicore Processeses & Threads Process A process is a self-contained computational unit with its own execution path and local resources. Memory Communication ports An application may be a single process or a set of processes communicating with each other (possibly on dierent physical machines.) Thread A thread, also known as a lightweight process , is an execution environment. Threads exist with a process and all the threads in a process share the local resources of the process, particularly local memory. While this makes communications between tasks very ecient via shared memory, it gives rise to several issues that need to be handled carefully.

Upload: others

Post on 04-Jul-2020

11 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

CA670 - Concurrent ProgrammingJava Threads

David Sinclair

Java Threads Synchronisation Multicore

Processeses & Threads

Process A process is a self-contained computational unit withits own execution path and local resources.

• Memory• Communication ports

An application may be a single process or a set ofprocesses communicating with each other (possiblyon different physical machines.)

Thread A thread, also known as a lightweight process, is anexecution environment. Threads exist with a processand all the threads in a process share the localresources of the process, particularly local memory.While this makes communications between tasks veryefficient via shared memory, it gives rise to severalissues that need to be handled carefully.

Page 2: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Threads in JavaEvery application starts with one default thread, the main thread.This thread, like any subsequently created thread, has the power tocreate and kill threads.

Each thread created is an instance of the Thread class.

There are two approaches to creating a thread.

p u b l i c c l a s s He l l oThread extends Thread{

p u b l i c vo id run ( ){

System . out . p r i n t l n ( ” He l l o World ! ” ) ;}

p u b l i c s t a t i c vo id main ( S t r i n g a r g s [ ] ){

(new He l l oThread ( ) ) . s t a r t ( ) ;}

}

Java Threads Synchronisation Multicore

Threads in Java (2)

While this is the easiest way, it is a bit restrictive in that your classis a subclass of Thread. A more general way is to make your classa subclass of Runnable. Thread is a subclass of Runnable, butRunnable inherits other classes that are useful for threadmanagement.

p u b l i c c l a s s He l l oRunnab l e implements Runnable{

p u b l i c vo id run ( ){

System . out . p r i n t l n ( ” He l l o aga in ! ” ) ;}

p u b l i c s t a t i c vo id main ( S t r i n g a r g s [ ] ){

(new Thread (new He l l oRunnab l e ( ) ) ) . s t a r t ( ) ;}

}

We will use this method.

Page 3: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Threads in Java (3)

Each thread has a priority from 1 to 10. The JVM uses apreemptive, priority-based scheduler that allocates the current timeslice as follows.

• The thread with the highest priority is selected.

• If two or more threads have the same priority, a first-infirst-out (FIFO) policy is followed.

• If the current thread is blocked or terminates, another threadis scheduled.

• If a thread with a higher priority is unblocked or started, itpreempts the current thread.

A thread can voluntary give up control calling the yield or sleepmethods. This voluntary yielding of control is called CooperativeMultitasking.

Java Threads Synchronisation Multicore

Yields, Sleeps & Interrupts

The yield method is a signal to the JVM that the thread is notdoing anything critical and is willing to let another thread run onthe JVM. The JVM is free to ignore the yield signal.

The sleep method suspends the current thread for the specifiedtime period and releases the JVM for another Runnable thread.

The interrupt method is a signal to a thread that it shouldpossibly take some new action. How a thread actually responds toan interrupt is solely at the thread’s discretion. Usually it wouldstop what it is currently doing.

There are 2 ways a thread can know if it has been interrupted.

• Catch an InterruptedException exception.

• Test the thread’s Interrupted flag by calling the interrupted

method.

Page 4: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Interrupted Examples

This example responds to an InterruptedException by stoppingit current activities.

t r y{

Thread . s l e e p ( 2000 ) ; // s l e e p f o r 2 seconds} catch ( I n t e r r u p t e dE x c e p t i o n e ){

r e t u r n ;}

This example test the Interrupted flag and throwing anInterruptedException.

i f ( Thread . i n t e r r u p t e d ( ) ){

throw new I n t e r r u p t e dE x c e p t i o n ( ) ;}

Java Threads Synchronisation Multicore

Joins

When a thread invokes the join method on another thread, it willwait for that thread to complete. It can be passed a parameter tospecify how long it should wait for the other thread to terminate

Like the sleep method, the join method also responds to aninterrupt signal with an InterruptedException.

Page 5: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

A Simple Example

From Oracle’s Java Tutorialsp u b l i c c l a s s SimpleThreads{

s t a t i c v o i d threadMessage ( S t r i n g message ){

S t r i n g threadName = Thread . cu r r en tTh read ( ) . getName ( ) ;System . out . fo rmat ( ”%s : %s%n” , threadName , message ) ;

}

p r i v a t e s t a t i c c l a s s MessageLoop implements Runnable{

p u b l i c v o i d run ( ){

S t r i n g impo r t a n t I n f o [ ] = {”Mares ea t oa t s ” , ”Does ea t oa t s ” ,” L i t t l e lambs ea t i v y ” , ”A k i d w i l l e a t i v y too ”} ;

t r y{

f o r ( i n t i = 0 ; i < impo r t a n t I n f o . l e n g t h ; i++){

Thread . s l e e p ( 4000 ) ;threadMessage ( impo r t a n t I n f o [ i ] ) ;

}} catch ( I n t e r r u p t e dE x c e p t i o n e ){

threadMessage ( ” I wasn ’ t done ! ” ) ;}

}}

Java Threads Synchronisation Multicore

A Simple Example (2)

p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) throws I n t e r r u p t e dE x c e p t i o n{

l ong p a t i e n c e = 1000 ∗ 60 ∗ 60 ;

i f ( a r g s . l e n g t h > 0){

t r y{

p a t i e n c e = Long . parseLong ( a r g s [ 0 ] ) ∗ 1000 ;} catch ( NumberFormatException e ){

System . e r r . p r i n t l n ( ”Argument must be an i n t e g e r . ” ) ;System . e x i t ( 1 ) ;

}}

threadMessage ( ” S t a r t i n g MessageLoop th r ead ” ) ;l ong s t a r tT ime = System . c u r r e n tT im eM i l l i s ( ) ;Thread t = new Thread (new MessageLoop ( ) ) ;t . s t a r t ( ) ;

Page 6: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

A Simple Example (3)

threadMessage ( ”Wait ing f o r MessageLoop th r ead to f i n i s h ” ) ;w h i l e ( t . i s A l i v e ( ) ){

threadMessage ( ” S t i l l w a i t i n g . . . ” ) ;t . j o i n ( 1 000 ) ;i f ( ( ( System . c u r r e n tT im eM i l l i s ( ) − s t a r tT ime ) > p a t i e n c e ) && t . i s A l i v e ( ) ){

threadMessage ( ” T i r ed o f wa i t i n g ! ” ) ;t . i n t e r r u p t ( ) ;t . j o i n ( ) ;

}}threadMessage ( ” F i n a l l y ! ” ) ;

}}

Java Threads Synchronisation Multicore

When Threads Go Bad!

Consider the following program.

p u b l i c c l a s s TwoThreads {

p r i v a t e s t a t i c c l a s s RugbyLoop implements Runnable{

p u b l i c v o i d run ( ){

t r y{

f o r ( i n t i = 0 ; i < 100 ; i++){

System . out . p r i n t ( ” I l i k e ” ) ;Thread . s l e e p ( 1 0 ) ;System . out . p r i n t l n ( ”Rugby” ) ;Thread . s l e e p ( 1 0 ) ;

}} catch ( I n t e r r u p t e dE x c e p t i o n e ){

System . out . p r i n t l n ( ”Rugby loop i n t e r r u p t e d ! ” ) ;}

}}

Page 7: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

When Threads Go Bad! (2)p r i v a t e s t a t i c c l a s s Ba l l e tLoop implements Runnable{

p u b l i c v o i d run ( ){

t r y{

f o r ( i n t i = 0 ; i < 100 ; i++){

System . out . p r i n t ( ” I hate ” ) ;Thread . s l e e p ( 1 0 ) ;System . out . p r i n t l n ( ” B a l l e t ” ) ;Thread . s l e e p ( 1 0 ) ;

}} catch ( I n t e r r u p t e dE x c e p t i o n e ){

System . out . p r i n t l n ( ” B a l l e t l oop i n t e r r u p t e d ! ” ) ;}

}}

p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) throws I n t e r r u p t e dE x c e p t i o n{

Thread r = new Thread (new RugbyLoop ( ) ) ;Thread b = new Thread (new Ba l l e tLoop ( ) ) ;

r . s t a r t ( ) ;b . s t a r t ( ) ;

r . j o i n ( ) ;b . j o i n ( ) ;

}}

Java Threads Synchronisation Multicore

When Threads Go Bad! (3)

When this program is executed the output may not be what wasintended. The problem is due to contention on a shared resource,2 threads trying to update a shared display.

While slightly amusing in this case, it can cause major systemsfailure in other cases. Consider a banking application where 2threads concurrently try to update your initial account balance ofe500 by e100 and e1000 respectively.

The relevant code in the 2 threads could be:

1.1 fload balance1.2 fadd 1001.3 fstore balance

2.1 fload balance2.2 fadd 10002.3 fstore balance

The interleaving {1.1,1.2,1.3,2.1,2.2,2.3} will give the “right”result, but the interleaving {2.1,2.2,1.1,2.3,1.2,1.3} will result ine1000 missing from the balance.

Page 8: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Critical Sections

The previous example shows us that some interleaving shouldnever be allowed. In general whenever a thread/process is updatingthe state of a shared resource, no other thread/process should beallowed to update the same shared resource while the firstthread/process is updating it. In this case the shared resource isthe shared variable balance.

These section of code that cannot be interleaved with relatedsections of code are called critical sections.

If a thread/process is executing a critical section associated with ashared variable balance, then it is OK if other threads areexecuting:

• code of non-critical sections; or

• code of critical sections associated with other sharedresources.

Java Threads Synchronisation Multicore

Synchronization

Many different techniques (semaphores, monitors, rendezvous,message passing) have been developed to ensure that 2 threads donot execute associated critical sections at the same time. Javauses a variation of the monitor concept called synchronization.

This comes in 2 forms:

• synchronized methods and;

• synchronized statements.

Page 9: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Synchronized Methodsp u b l i c c l a s s BankAccount {

p r i v a t e i n t ba l ance = 0 ;. . .

p u b l i c synchron ized vo id d e p o s i t ( f l o a t amount ){

ba l ance = ba l ance + amount ;}

. . .}

A synchronized method has 2 effects:

• 2 invocations of synchronized methods on the same objectcannot execute at the same time. When a thread is executinga synchronized method of an object, then all other threadsthat invoke any synchronized methods for the same object areblocked and execution is suspended until the first thread isdone with the object.

Java Threads Synchronisation Multicore

Synchronized Methods (2)

• When a synchronized method exits, it creates ahappens-before relationship with any subsequent invocation ofany synchronized method of the same object. This guaranteesthat changes to the state of the object are visible to allthreads.

Synchronization is built around an internal entity known as theintrinsic lock or monitor lock. Every object has an intrinsic lock(also known as a monitor lock) associated with it. A thread thatneeds exclusive access to an object’s fields needs to acquire theobject’s intrinsic lock before accessing them, and then release theintrinsic lock when it is finished. As long as a thread owns theintrinsic lock, any other thread will block when it attempts toacquire the lock.

Page 10: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Synchronized Statements

The following example synchronises on updating the membervariable balance but allow concurrent invocation of thecheck owner method by many threads.

p u b l i c vo id d e p o s i t ( S t r i n g name , f l o a t ba l ance ){

i f ( check owner ( name ) ){

synchron ized ( t h i s ){

ba l ance = ba l ance + amount ;}

}}

Java Threads Synchronisation Multicore

Synchronized Statements (2)Synchronized statements must specify the object that provides theintrinsic lock, though it can be any object.p u b l i c c l a s s MsLunch{

p r i v a t e long c1 = 0 , c2 = 0 ;p r i v a t e Object l o c k1 = new Object ( ) , l o c k2 = new Object ( ) ;

p u b l i c v o i d i n c 1 ( ){

s y n c h r o n i z e d ( l o c k1 ){

c1++;}

}

p u b l i c v o i d i n c 2 ( ){

s y n c h r o n i z e d ( l o c k2 ){

c2++;}

}}

Page 11: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Reentrant Synchronization

A thread cannot acquire a lock owned by another thread, But itcan acquire a lock that it already owns. Allowing a thread toacquire the same lock more than once enables reentrantsynchronization. This allows a thread to directly or indirectlyinvoke a method that also contains synchronized code, and boththe calling code and the called code use the same lock. Otherwisewithout reentrant synchronization, we would have very complexcode to avoid having a thread causing itself to block.

Java Threads Synchronisation Multicore

Atomic Access

An atomic action is one that happens all at once. It cannot bestopped in the middle. It either happens completely, or it doesn’thappen at all.

The following are atomic actions.

• Reads from and writes to reference variables and for mostprimitive variables (all types except long and double).

• Reads from and writes to all variables declared volatile(including long and double variables).

Using simple atomic variable access is more efficient than accessingthese variables through synchronized code, but does define theorder in which the different threads perform the atomic accesses.

Page 12: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Deadlock

Deadlock occurs where two or more threads are blocked forever,typically waiting for each other.

Consider the following problem called the Dining PhilosophersProblem. An institution hires five philosophers to solve a verydifficult problem. Each philosopher only engages in two activities -thinking and eating. Meals are taken in the dining room which hasa table set with five plates and five forks. In the centre of the tableis a bowl of spaghetti that is endlessly replenished. Thephilosophers, not being the most dextrous of individuals, requiretwo forks to eat; and may only pick up the forks immediately to hisleft and right.

Java Threads Synchronisation Multicore

Deadlock (2)

For this system to operate correctly it is required that:

• A philosopher eats only if he has two forks.

• No two philosophers can hold the same fork simultaneously.

• No deadlock.

• No individual starvation.

• Efficient behaviour under the absence of contention.

This problem is a generalisation of multiple processes accessing aset of shared resources; e.g. a network of computers accessing anarray of storage disks.

Page 13: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Deadlock (3)We can model exclusive access to each fork by using synchronizedstatements.c l a s s Ph i l o s o ph e r implements Runnable{

p u b l i c f i n a l i n t i d ;p r i v a t e f i n a l Chops t i c k [ ] c h o p s t i c k s ;p r o t e c t e d f i n a l Chops t i ckOrde r o r d e r ;

p u b l i c Ph i l o s o ph e r ( i n t id , Chops t i c k [ ] c h op s t i c k s ,Chops t i ckOrde r o r d e r )

{t h i s . i d = i d ;t h i s . c h o p s t i c k s = c h o p s t i c k s ;t h i s . o r d e r = o rd e r ;

}

p u b l i c v o i d run ( ){

w h i l e ( t r u e ){

ea t ( ) ;}

}

Java Threads Synchronisation Multicore

Deadlock (4)p r o t e c t e d v o i d ea t ( ){

Chops t i c k [ ] c hop s t i c kO rd e r = o rd e r . ge tOrde r ( g e t L e f t ( ) ,g e tR i gh t ( ) ) ;

s y n c h r o n i z e d ( c hop s t i c kO rd e r [ 0 ] ){

s y n c h r o n i z e d ( c hop s t i c kO rd e r [ 1 ] ){

U t i l . s l e e p ( 1000 ) ;}

}}

Chops t i c k g e t L e f t ( ){

r e t u r n c h o p s t i c k s [ i d ] ;}

Chops t i c k ge tR i gh t ( ){

r e t u r n c h o p s t i c k s [ ( i d +1) % ch o p s t i c k s . l e n g t h ] ;}

}

Page 14: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Deadlock (5)

This is called a symmetric solution since each task is identical.Symmetric solutions have many advantages, particularly when itcomes to load-balancing.

However, this system can deadlock under an interleaving in whichall five philosophers pick up their left forks together.

There are several solutions.

• Make one of the philosophers pick up the right fork before theleft fork (asymmetric solution).

• Make a philosopher release their left fork if they cannot securetheir right fork.

• Only allow four philosophers into the room at any one time.

Java Threads Synchronisation Multicore

Lock Objects

In order to provide a more sophisticate locking mechanism thansynchronized code, Java provides thejava.util.concurrent.locks package. In particular we willfocus on its most basic interface, Lock.

Lock objects work very much like the implicit locks used bysynchronized code. As with implicit locks, only one thread can owna Lock object at a time. Lock objects provide a more sophisticatedimplementation of monitors by providing a wait/notify mechanism,through their associated Condition objects.

The main advantage of Lock objects over implicit locks is theirability to back out of an attempt to acquire a lock. The tryLock

method backs out if the lock is not available immediately or beforea specified timeout has expired. The lockInterruptibly methodbacks out if another thread sends an interrupt before the lock isacquired.

Page 15: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Lock Objects (2)

p u b l i c c l a s s Gr a c i o u sPh i l o s o ph e r extends Ph i l o s o ph e r{

p r i v a t e s t a t i c Map chop s t i c kLo ck s = new ConcurrentHashMap ( ) ;

p u b l i c Gr a c i o u sPh i l o s o ph e r ( i n t id , Chops t i c k [ ] c h op s t i c k s ,Chops t i ckOrde r o r d e r )

{super ( id , c h op s t i c k s , o r d e r ) ;

// Every p h i l o s o p h e r c r e a t e s a l o c k// f o r t h e i r l e f t c h o p s t i c kchop s t i c kLo c k s . put ( g e t L e f t ( ) , new Reent rantLock ( ) ) ;

}

p r o t e c t e d v o i d ea t ( ){

Chops t i c k [ ] c hop s t i c kO rd e r = o rd e r . ge tOrde r ( g e t L e f t ( ) ,g e tR i gh t ( ) ) ;

Lock f i r s t L o c k = chop s t i c kLo ck s . ge t ( c hop s t i c kO rd e r [ 0 ] ) ;Lock secondLock = chop s t i c kLo ck s . ge t ( c hop s t i c kO rd e r [ 1 ] ) ;

Java Threads Synchronisation Multicore

Lock Objects (3)

f i r s t L o c k . l o c k ( ) ;t r y{

secondLock . l o c k ( ) ;t r y{

s l e e p ( 1000 ) ;} f i n a l l y{

secondLock . un lock ( ) ;}

} f i n a l l y{

f i r s t L o c k . un lock ( ) ;}

}}

Page 16: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Lock Objects (4)

Or using the tryLock method

p u b l i c c l a s s Gr a c i o u sPh i l o s o ph e r extends Ph i l o s o ph e r{

p r i v a t e s t a t i c Map chop s t i c kLo ck s = new ConcurrentHashMap ( ) ;

p u b l i c Gr a c i o u sPh i l o s o ph e r ( i n t id , Chops t i c k [ ] c h op s t i c k s ,Chops t i ckOrde r o r d e r )

{super ( id , c h op s t i c k s , o r d e r ) ;

// Every p h i l o s o p h e r c r e a t e s a l o c k// f o r t h e i r l e f t c h o p s t i c kchop s t i c kLo c k s . put ( g e t L e f t ( ) , new Reent rantLock ( ) ) ;

}

p r o t e c t e d v o i d ea t ( ){

Chops t i c k [ ] c hop s t i c kO rd e r = o rd e r . ge tOrde r ( g e t L e f t ( ) ,g e tR i gh t ( ) ) ;

Lock f i r s t L o c k = chop s t i c kLo ck s . ge t ( c hop s t i c kO rd e r [ 0 ] ) ;Lock secondLock = chop s t i c kLo ck s . ge t ( c hop s t i c kO rd e r [ 1 ] ) ;

Java Threads Synchronisation Multicore

Lock Objects (5)

Boolean l e f t L o c k = f a l s e , r i g h t L o c k = f a l s e ;

t r y{

l e f t L o c k = f i r s t L o c k . t r yLock ( ) ;r i g h t L o c k = secondLock . t r yLock ( ) ;

} f i n a l l y{

i f ( l e f t L o c k && r i g h t Lo c k ){

s l e e p ( 1000 ) ; // ea t}

i f ( l e f t L o c k ) f i r s t L o c k . un lock ( ) ;i f ( r i g h t L o c k ) secondLock . un lock ( ) ;

}}

}

We still have some issues with this solution. Though there is nodeadlock, there is the possibility of individual threads starving andfairness to the access of the shared resource.

Page 17: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

wait() & notify()

synchronized methods and blocks acquire and release a lockwithin a method. To have one method acquire a lock and anotherrelease it, you need to use the wait-notify mechanism.

• wait() tells the calling thread to give up the monitor and goto sleep until some other thread enters the same monitor(object) and calls notify( ).

• notify() wakes up the first thread that called wait() on thesame object.

• notifyAll() wakes up all threads blocked on the sameobject.

Java Threads Synchronisation Multicore

wait() & notify() (2)

p u b l i c c l a s s ThreadA{

p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ){

ThreadB b = new ThreadB ( ) ;b . s t a r t ( ) ;

s y n c h r o n i z e d ( b ){

t r y{

System . out . p r i n t l n ( ”Wait ing f o r b to complete . . ” ) ;b . wa i t ( ) ;

} catch ( I n t e r r u p t e dE x c e p t i o n e ){

e . p r i n t S t a c kT r a c e ( ) ;}System . out . p r i n t l n ( ” Tota l i s : ” + b . t o t a l ) ;

}}

}

Page 18: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

wait() & notify() (3)

c l a s s ThreadB extends Thread{

i n t t o t a l ;

@Over r idep u b l i c v o i d run ( ){

s y n c h r o n i z e d ( t h i s ){

f o r ( i n t i =0; i <100 ; i++){

t o t a l += i ;}n o t i f y ( ) ;

}}

}

Java Threads Synchronisation Multicore

Condition Variables

Condition variables factor out and Object’s wait, notify andnotifyAll methods into distinct objects to give the effect ofhaving multiple wait-sets per object.

A Condition instance is intrinsically bound to a lock. To obtain aCondition instance for a particular Lock instance use itsnewCondition() method.

A common paradigm for concurrent programming is theProducer-Consumer paradigm in which Producers generates workfor multiple Consumers to process. The Producers are connectedto the Consumers via a bounded buffer.

Page 19: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Condition Variables (2)

The Condition object has the following methods:

• await(): The current thread will wait until it is signalled orinterrupted.

• await(long time, TimeUnit units): The current thread willwait for the specified time period or until it is signalled orinterrupted.

• awaitNanos(long time): The current thread will wait for thespecified number of nanoseconds or until it is signalled orinterrupted.

• awaitUninterruptibly(): The current thread will wait until itis signalled.

• awaitUntil(Date deadline): The current thread will wait forthe specified deadline to elapse, or until it is signalled orinterrupted.

Java Threads Synchronisation Multicore

Condition Variables (3)

• signal(): Wakes up the next waiting thread.

• signal(): Wakes up all waiting threads.

A Condition object is just a normal object and can be used as theargument of a synchronized statement, and can have its ownmonitor wait() and notify() methods invoked. To avoid confusionyou should never use Condition instances in this way.

In order to simplify the implementation of Condition, spuriouswakeups are allowed to occur while waiting for the Condition. Inpractice this has little impact as a Condition should always bewaited upon in a loop, testing the logical condition that is beingwaited for. A given implementation can remove the possibility ofspurious wakeups, but applications programmers should alwaysassume that they can occur and so always wait in a loop.

Page 20: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Producer-Consumerc l a s s BoundedBuf fer{

f i n a l Lock l o c k = new Reent rantLock ( ) ;f i n a l Cond i t i on n o t F u l l = l o c k . newCond i t ion ( ) ;f i n a l Cond i t i on notEmpty = l o c k . newCond i t ion ( ) ;f i n a l Object [ ] i t ems = new Object [ 1 0 0 ] ;i n t putpt r , t akep t r , count ;

p u b l i c v o i d put ( Object x ) throws I n t e r r u p t e dE x c e p t i o n{

l o c k . l o c k ( ) ;t r y{

w h i l e ( count == i t ems . l e n g t h ){

n o t F u l l . awa i t ( ) ;}

i t ems [ pu t p t r ] = x ;i f (++pu tp t r == i t ems . l e n g t h ){

pu tp t r = 0 ;}

++count ;notEmpty . s i g n a l ( ) ;

} f i n a l l y{

l o c k . un lock ( ) ;}

}

Java Threads Synchronisation Multicore

Producer-Consumer (2)

p u b l i c Object take ( ) throws I n t e r r u p t e dE x c e p t i o n{

l o c k . l o c k ( ) ;t r y{

w h i l e ( count == 0){

notEmpty . awa i t ( ) ;}

Object x = i t ems [ t a k e p t r ] ;i f (++t a k e p t r == i t ems . l e n g t h ){

t a k e p t r = 0 ;}

−−count ;n o t F u l l . s i g n a l ( ) ;r e t u r n x ;

} f i n a l l y{

l o c k . un lock ( ) ;}

}}

Page 21: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Running Threads on Different Cores

We have seen how to create multiple threads and coordinate themvia synchronized methods and blocks, as well as via Lock

objects. But how do we execute the threads to different cores on amulticore machine?

There are 2 mechanisms in Java

• Executors Interface and Thread Pools

• Fork/Join Framework

Java Threads Synchronisation Multicore

Executor Interface & Thread Pools

The java.util.concurrent package provides 3 executorinterfaces.

• Executor: A simple interface that launches new tasks.

• ExecutorService: A subinterface of Executor that addsfeatures that help manage tasks’ lifecycle.

• ScheduledExecutorService: A subinterface ofExecutorService that supports future and/or periodicexecution of tasks.

The Executor interface provides a single method, execute. If r isa Runnable object, and e is an Executor object then

e . e x e cu t e ( r ) ;

may simply execute a thread, or it may use an existing workerthread to run r, or using thread pools it may place r in a queue towait for a worker thread to become available.

Page 22: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Executor Example

p u b l i c c l a s s WorkerThread implements Runnable{

p r i v a t e S t r i n g command ;

p u b l i c WorkerThread ( S t r i n g s ){

t h i s . command=s ;}

@Over r idep u b l i c v o i d run ( ){

System . out . p r i n t l n ( Thread . cu r r en tTh r ead ( ) . getName()+” S t a r t . Command = ”+command ) ;

processCommand ( ) ;System . out . p r i n t l n ( Thread . cu r r en tTh r ead ( ) . getName()+

” End . ” ) ;}

Java Threads Synchronisation Multicore

Executor Example (2)

p r i v a t e v o i d processCommand ( ){

t r y{

Thread . s l e e p ( 5000 ) ;} catch ( I n t e r r u p t e dE x c e p t i o n e ){

e . p r i n t S t a c kT r a c e ( ) ;}

}

@Over r idep u b l i c S t r i n g t o S t r i n g ( ){

r e t u r n t h i s . command ;}

}

Page 23: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Executor Example (3)import j a v a . u t i l . c o n cu r r e n t . E x e c u t o r S e r v i c e ;import j a v a . u t i l . c o n cu r r e n t . Execu to r s ;

p u b l i c c l a s s SimpleThreadPoo l{

p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ){

Ex e c u t o r S e r v i c e e x e cu t o r =Execu to r s . newFixedThreadPool ( 1 0 ) ;

f o r ( i n t i = 0 ; i < 20 ; i++){

Runnable worker = new WorkerThread ( ”” + i ) ;e x e cu t o r . e x e cu t e ( worker ) ;

}e x e cu t o r . shutdown ( ) ;w h i l e ( ! e x e cu t o r . i sTe rm ina t ed ( ) ){}

System . out . p r i n t l n ( ” F i n i s h e d a l l t h r e a d s ” ) ;}

}

Java Threads Synchronisation Multicore

Fork/Join Framework

Since Java 7, the Fork/Join framework has been available todistribute threads among multiple cores. This framework adopts adivide-and-conquer approach. If a task can be easily solved thecurrent thread returns its result. Otherwise the thread divides thetask into simpler tasks and forks a thread for each sub-task. Whenall the sub-tasks are completed, the current thread returns itsresult obtained from combining the results of its sub-tasks.

The key difference between the Fork/Join framework and ExecutorInterface is that the Fork/Join framework implements a workstealing algorithm whereby idle threads steal work from threadsthat are still busy.

Page 24: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Fork/Join ClassesA key class is the ForkJoinPool which is an implementation ofthe ExecutorService that implements the work-stealingalgorithm. A ForkJoinPool is instantiated as follows.

numberOfCores = Runtime . getRunTIme ( ) . a v a i l a b l e P r o c e s s o r s ( ) ;Fo rkJo inPoo l poo l = new ForkJo inPoo l ( numberOfCores ) ;

The size of the pool at any point in time will be adjustedautomatically to maintain enough active threads. Unlike theExecutorService the ForJoinPool does not need to beexplicitly shutdown.

There are 3 ways to submit tasks to a ForkJoinPool

• execute(): asynchronous execution

• invoke(): synchronous execution - wait for the result

• invoke(): asynchronous execution - returns a Future objectthat can be used to check the status of the execution andobtain the results.

Java Threads Synchronisation Multicore

Fork/Join Classes (2)

The ForkJoinTask class is an abstract class that is used to createtasks to be executed from the ForkJoinPool. There are 2subclasses:

• RecursiveTask: returns an object of a specified type.

• RecursiveAction: has no return object.

The status of a task can be checked using:

• isDone(): returns true if the tasks has finished execution.

• isCompletedNormally(): returns true if the task hascompleted without cancellation or exception.

• isCancelled(): returns true if the task has been cancelled.

• isCompletedAbnormally(): returns true if the task hasbeen terminated by an exception.

Page 25: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Fork/Join Exampleimport j a v a . u t i l . Random ;import j a v a . u t i l . c o n cu r r e n t . Fo rkJo inPoo l ;import j a v a . u t i l . c o n cu r r e n t . Recu r s i v eTask ;

p u b l i c c l a s s MaximumFinder extends Recur s i veTask<I n t e g e r>{

p r i v a t e s t a t i c f i n a l i n t SEQUENTIAL THRESHOLD = 5 ;

p r i v a t e f i n a l i n t [ ] data ;p r i v a t e f i n a l i n t s t a r t ;p r i v a t e f i n a l i n t end ;

p u b l i c MaximumFinder ( i n t [ ] data , i n t s t a r t , i n t end ){

t h i s . data = data ;t h i s . s t a r t = s t a r t ;t h i s . end = end ;

}

p u b l i c MaximumFinder ( i n t [ ] data ){

t h i s ( data , 0 , data . l e n g t h ) ;}

Java Threads Synchronisation Multicore

Fork/Join Example (2)

@Over r idep r o t e c t e d I n t e g e r compute ( ){

f i n a l i n t l e n g t h = end − s t a r t ;i f ( l e n g t h < SEQUENTIAL THRESHOLD){

r e t u r n comput eD i r e c t l y ( ) ;}f i n a l i n t s p l i t = l e n g t h / 2 ;f i n a l MaximumFinder l e f t = new MaximumFinder ( data , s t a r t ,

s t a r t + s p l i t ) ;l e f t . f o r k ( ) ;f i n a l MaximumFinder r i g h t = new MaximumFinder ( data ,

s t a r t + s p l i t , end ) ;r e t u r n Math .max( r i g h t . compute ( ) , l e f t . j o i n ( ) ) ;

}

Page 26: CA670 - Concurrent Programmingdavids/courses/CA670... · Java ThreadsSynchronisationMulticore CA670 - Concurrent Programming Java Threads David Sinclair Java ThreadsSynchronisationMulticore

Java Threads Synchronisation Multicore

Fork/Join Example (3)

p r i v a t e I n t e g e r comput eD i r e c t l y ( ){

System . out . p r i n t l n ( Thread . cu r r en tTh r ead ( ) + ” computing : ”+ s t a r t + ” to ” + end ) ;

i n t max = I n t e g e r .MIN VALUE ;f o r ( i n t i = s t a r t ; i < end ; i++){

i f ( data [ i ] > max){

max = data [ i ] ;}

}

r e t u r n max ;}

Java Threads Synchronisation Multicore

Fork/Join Example (4)

p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ){

// c r e a t e a random data s e tf i n a l i n t [ ] data = new i n t [ 1 0 0 0 0 ] ;f i n a l Random random = new Random ( ) ;f o r ( i n t i = 0 ; i < data . l e n g t h ; i++){

data [ i ] = random . n e x t I n t ( 1 0 0 ) ;}

// submit the t a s k to the poo lf i n a l ForkJo inPoo l poo l = new ForkJo inPoo l ( 4 ) ;f i n a l MaximumFinder f i n d e r = new MaximumFinder ( data ) ;System . out . p r i n t l n ( poo l . i n voke ( f i n d e r ) ) ;

}}