64
Counting Semaphore Counting Semaphore Implementation in Java Implementation in Java CS598 – Concurrent Programming CS598 – Concurrent Programming Kasturi Kallakuri Kasturi Kallakuri Cindy Mayo Cindy Mayo 21 21 August 2002 August 2002

Counting Semaphore Implementation in Java

Embed Size (px)

DESCRIPTION

Counting Semaphore Implementation in Java. CS598 – Concurrent Programming. Kasturi Kallakuri Cindy Mayo 21 August 2002. “Alfonse, Wait Here for My Signal!”. Author: Stephen J. Hartley Original presentation: ACM-SIGCSE March 1999 New Orleans, Louisiana. 1 Java is Multithreaded. - PowerPoint PPT Presentation

Citation preview

Page 1: Counting Semaphore Implementation in Java

Counting SemaphoreCounting SemaphoreImplementation in JavaImplementation in Java

CS598 – Concurrent ProgrammingCS598 – Concurrent Programming

Kasturi KallakuriKasturi Kallakuri

Cindy MayoCindy Mayo 21 21 August 2002August 2002

Page 2: Counting Semaphore Implementation in Java

““Alfonse, Wait HereAlfonse, Wait Herefor My Signal!”for My Signal!”

Author: Stephen J. HartleyAuthor: Stephen J. Hartley

Original presentation:Original presentation:

ACM-SIGCSE March 1999ACM-SIGCSE March 1999

New Orleans, LouisianaNew Orleans, Louisiana

Page 3: Counting Semaphore Implementation in Java

1 Java is Multithreaded1 Java is Multithreaded

The Java Virtual Machine can The Java Virtual Machine can support many threads of support many threads of execution at a timeexecution at a time• A thread is a separate flow of A thread is a separate flow of

control within a programcontrol within a program• Each thread has its own local Each thread has its own local

variables and lifetimevariables and lifetime

Page 4: Counting Semaphore Implementation in Java

1 Java is Multithreaded1 Java is Multithreaded

• All threads within a program All threads within a program share the same address spaceshare the same address space

• Thread is represented by the Java Thread is represented by the Java Thread classThread class

• Threads can be synchronized with Threads can be synchronized with other threads in same processother threads in same process

Page 5: Counting Semaphore Implementation in Java

ThreadsPROGRAM

HotJava Web Browser is an example of a multithread Java application

1.1 A Multithreaded 1.1 A Multithreaded ProgramProgram

Page 6: Counting Semaphore Implementation in Java

1.2 Thread Creation1.2 Thread Creation

Implement the Runnable Implement the Runnable InterfaceInterface

Subclass (extend) the Thread Subclass (extend) the Thread classclass

Page 7: Counting Semaphore Implementation in Java

1.2.1 Implementing 1.2.1 Implementing RunnableRunnable

class HelloRunnable implements Runnable{public void run(){ System.out.println(“Hello World!”);}

}

HelloRunnable hr = new HelloRunnable();Thread hThread = new Thread(hr);hThread.start()

Page 8: Counting Semaphore Implementation in Java

1.2.2 Subclassing 1.2.2 Subclassing ThreadThread

class HelloThread extends Thread{ public void run({ System.out.println(“HelloWorld!”); }

}

HelloThread hThread = new HelloThread();hThread.start()

Page 9: Counting Semaphore Implementation in Java

start()

quantum expiration“yield” interrupt

dispatch

wait()sleep() complete

issue I/Orequest

I/O completion

sleep interval expires

notify()notifyAll()

1.3 Life Cycle of a 1.3 Life Cycle of a ThreadThread

waiting sleeping dead blocked

running

born

ready

Page 10: Counting Semaphore Implementation in Java

1.4 Thread Priorities1.4 Thread Priorities

By default, all threads have equal By default, all threads have equal prioritypriority

setPriority() can be used to change setPriority() can be used to change the default prioritythe default priority

Java implements MIN_PRIORITY (0) Java implements MIN_PRIORITY (0) and MAX_PRIORITY (10)and MAX_PRIORITY (10)

Microsoft’s JVM utilizes time slicingMicrosoft’s JVM utilizes time slicing Solaris’ JVM does notSolaris’ JVM does not

Page 11: Counting Semaphore Implementation in Java

2 Object Locks2 Object Locks

Every Java Object has a lock, which Every Java Object has a lock, which is implemented as a binary is implemented as a binary semaphoresemaphore

Java supports mutual exclusion Java supports mutual exclusion through the through the synchronizedsynchronized keyword keyword

Object locks may be class locks or Object locks may be class locks or class instance locks.class instance locks.

Page 12: Counting Semaphore Implementation in Java

2 Object Locks2 Object Locks Java does not provide a way to Java does not provide a way to

perform separate locking and perform separate locking and unlocking functionsunlocking functions

lock()lock() and and unlock()unlock() are implicitly are implicitly performed by high-level constructs performed by high-level constructs that arrange ways to pair such actions that arrange ways to pair such actions correctlycorrectly

The JVM provides separate The JVM provides separate monitorenter and monitorexit monitorenter and monitorexit instructions that implement the lock instructions that implement the lock and unlock actionsand unlock actions

Page 13: Counting Semaphore Implementation in Java

2.1 Mutual Exclusion 2.1 Mutual Exclusion

Synchronized blocksSynchronized blocks Synchronized methodsSynchronized methods

Page 14: Counting Semaphore Implementation in Java

2.1.1 Synchronized block2.1.1 Synchronized block Acquires the object lock before Acquires the object lock before

executing the body of the executing the body of the synchronized blocksynchronized block

After execution of the block, unlocks After execution of the block, unlocks the lockthe lock

Syntax:Syntax:

Object obj = new Object();Object obj = new Object();synchronizedsynchronized (obj) (obj){{// critical section// critical section

}}

Page 15: Counting Semaphore Implementation in Java

2.1.1 Synchronized block2.1.1 Synchronized block

class Update { private int data = 0; public void increment(){ synchronized(this) { //lock the object

data++; } }//end of increment } //end of class

Page 16: Counting Semaphore Implementation in Java

2.1.2 Synchronized 2.1.2 Synchronized methodmethod

Automatically performs lock action Automatically performs lock action when invokedwhen invoked

After execution of the After execution of the method’sbody,unlock action is method’sbody,unlock action is automatically performed on same lockautomatically performed on same lock

Syntax:Syntax:

Object obj = new obj();//methods use synchronized type method(…){ //body of method }

Page 17: Counting Semaphore Implementation in Java

2.1.2 Synchronized 2.1.2 Synchronized methodmethod

bump()bump() uses an instance lock ( uses an instance lock (thisthis)) classBump()classBump() uses the class lock uses the class lock

class Test {class Test {

int count;int count;static int classCount;static int classCount;synchronized void synchronized void bump()bump(){ count++; }{ count++; }static synchronized void static synchronized void classBump()classBump(){ classCount++; }{ classCount++; }

}}

Page 18: Counting Semaphore Implementation in Java

2.2 2.2 ConditionalSynchronizatiConditionalSynchronizationon

Waiting process should leave the Waiting process should leave the semaphore but not exit the methodsemaphore but not exit the method

Leaving the object instance Leaving the object instance releases the lockreleases the lock

Instances need back porch where Instances need back porch where waiters leave and not exit the waiters leave and not exit the instance. [wait set]instance. [wait set]

There is only one wait set per class There is only one wait set per class instanceinstance

Page 19: Counting Semaphore Implementation in Java

2.2 Conditional 2.2 Conditional SynchronizationSynchronization

Object method wait() blocks calling Object method wait() blocks calling thread in wait set.thread in wait set.

Object method notify() unblocks a Object method notify() unblocks a thread if any in the wait setthread if any in the wait set

Object method notifyAll() unblocks Object method notifyAll() unblocks all threads in the wait set.all threads in the wait set.

Page 20: Counting Semaphore Implementation in Java

2.3 Deadlock2.3 Deadlock

Java does not prevent, nor require Java does not prevent, nor require detection of deadlock conditionsdetection of deadlock conditions

Programs where threads hold locks Programs where threads hold locks on multiple objects should use on multiple objects should use conventional techniques for conventional techniques for avoiding deadlockavoiding deadlock• Create higher level locking Create higher level locking

primitives that cannot deadlock, primitives that cannot deadlock, if necessaryif necessary

Page 21: Counting Semaphore Implementation in Java

2.3.1 Mutex behaviour2.3.1 Mutex behaviour

Mutex unblocking is arbitaryMutex unblocking is arbitary Thread priority is ignoredThread priority is ignored Thread starvation is possibleThread starvation is possible Mutex locking is re-entrantMutex locking is re-entrant A thread can relock any mutex it A thread can relock any mutex it

holdsholds

Page 22: Counting Semaphore Implementation in Java

2.3.2 Interference2.3.2 Interference

Interference with conditional Interference with conditional synchronizationsynchronization

Unblocked thread may not Unblocked thread may not immediately regain the muteximmediately regain the mutex

The signaled condition may no The signaled condition may no longer be true when it doeslonger be true when it does

Page 23: Counting Semaphore Implementation in Java

2.4 Points to 2.4 Points to RememberRemember The acquisition and release of locks The acquisition and release of locks

is done automatically and is done automatically and atomically by the Java Virtual atomically by the Java Virtual Machine (JVM), which guarantees Machine (JVM), which guarantees that:that:• Race conditions cannot occurRace conditions cannot occur• Data integrity is ensuredData integrity is ensured

Mutex behaviour needs to be worked around

Page 24: Counting Semaphore Implementation in Java

3 Java Monitors3 Java Monitors

Monitors are a data abstract Monitors are a data abstract mechanismmechanism

Monitors encapsulate data without Monitors encapsulate data without external access and references external access and references outside of the monitor are blockedoutside of the monitor are blocked

Monitors contain variables that Monitors contain variables that store the object’s state and store the object’s state and procedures that implement procedures that implement operations on the objectoperations on the object

Page 25: Counting Semaphore Implementation in Java

3 Java Monitors3 Java Monitors

Mutual exclusionMutual exclusion is provided is provided implicitly by ensuring that implicitly by ensuring that procedures in the same monitor are procedures in the same monitor are not executed concurrentlynot executed concurrently

Condition synchronizationCondition synchronization is is provided explicitly by condition provided explicitly by condition variablesvariables

Page 26: Counting Semaphore Implementation in Java

class Monitor { private .. //data fields Monitor(..){…} //constructor synchronized type method1(){ notifyAll();

while ( !condition ) try { wait(); } catch(InterruptedException e){}notifyAll();

}

Note: Monitors are compile time entities

3.1 Java Monitor 3.1 Java Monitor StructureStructure

Page 27: Counting Semaphore Implementation in Java

3.2 Concurrency 3.2 Concurrency ControlControl Mutual ExclusionMutual Exclusion Conditional SynchronizationConditional Synchronization

Page 28: Counting Semaphore Implementation in Java

3.2.1 Mutual Exclusion3.2.1 Mutual Exclusion

A monitor procedure is called by an A monitor procedure is called by an external processexternal process

At most, one instance of monitor At most, one instance of monitor procedure may be active at a timeprocedure may be active at a time

Only one thread at a time is Only one thread at a time is allowed inside the monitorallowed inside the monitor

Page 29: Counting Semaphore Implementation in Java

3.2.1 Mutual Exclusion3.2.1 Mutual Exclusion

Monitor entries are (java) Monitor entries are (java) synchronized always.synchronized always.

Monitor procedures by definition Monitor procedures by definition execute with mutual exclusionexecute with mutual exclusion

It is up to the language and It is up to the language and operating system to provide mutual operating system to provide mutual exclusionexclusion

Page 30: Counting Semaphore Implementation in Java

3.2.2 Condition 3.2.2 Condition SynchronizationSynchronization A condition variable is used to A condition variable is used to

delay a process that cannot safely delay a process that cannot safely continue executing until the continue executing until the monitor’s state satisfies some monitor’s state satisfies some Boolean conditionBoolean condition

There may be many condition There may be many condition variables per monitorvariables per monitor

Monitor’s back porchMonitor’s back porch

Page 31: Counting Semaphore Implementation in Java

3.2.2 Condition 3.2.2 Condition SynchronizationSynchronization A process queries the state of a A process queries the state of a

condition variable by calling condition variable by calling empty()empty()

A process blocks on a condition A process blocks on a condition variable by calling wait()variable by calling wait()

Processes blocked on a condition Processes blocked on a condition variable are awakened by a call to variable are awakened by a call to signal()signal()

Page 32: Counting Semaphore Implementation in Java

callmonitor

free

wait()Signal andcontinue

return

Conditionvariablequeue

Executingin monitor

Entryqueue

3.3 Signal and Continue3.3 Signal and Continue

Page 33: Counting Semaphore Implementation in Java

3.3 Signal and Continue3.3 Signal and Continue

Signal and continue is non Signal and continue is non preemptivepreemptive

Condition variable release is Condition variable release is FIFOFIFO

Relation between signaled and Relation between signaled and signaler:signaler:• Signaled jumps to the front of the Signaled jumps to the front of the

entry queue signaler continues entry queue signaler continues

Page 34: Counting Semaphore Implementation in Java

3.4 Perils of Monitors3.4 Perils of Monitors

The thread blocked longest on a The thread blocked longest on a monitor synchronized method call monitor synchronized method call is is notnot guaranteed to be next thread guaranteed to be next thread to acquire the monitor lock when to acquire the monitor lock when the monitor lock is releasedthe monitor lock is released

Page 35: Counting Semaphore Implementation in Java

3.4 Perils of Monitors3.4 Perils of Monitors

The thread blocked the longest in a The thread blocked the longest in a wait() call is not guaranteed to be wait() call is not guaranteed to be the one removed from the wait set the one removed from the wait set when a notify() call is madewhen a notify() call is made

Typically, FIFO is used to determine Typically, FIFO is used to determine who gets control (JVM/platform who gets control (JVM/platform specific)specific)

Page 36: Counting Semaphore Implementation in Java

3.4 Perils of Monitors3.4 Perils of Monitors

A thread waiting for the monitor A thread waiting for the monitor lock to execute a monitor lock to execute a monitor synchronized method might get the synchronized method might get the lock before a signaled thread lock before a signaled thread reacquires the lock even if the reacquires the lock even if the notify occurred earlier than the notify occurred earlier than the monitor method callmonitor method call

A thread should always recheck its A thread should always recheck its wait condition when signaledwait condition when signaled

Page 37: Counting Semaphore Implementation in Java

3.4 Perils of Monitors3.4 Perils of Monitors

The while construct is preferred The while construct is preferred over the if constructover the if construct

while ( !condition )while ( !condition )

wait();wait();

notifyAll();notifyAll();

Page 38: Counting Semaphore Implementation in Java

3.4 Perils of Monitors3.4 Perils of Monitors

Each monitor has a single, Each monitor has a single, nameless condition variablenameless condition variable

Cannot specify which of the waiting Cannot specify which of the waiting threads should be released by a threads should be released by a notify()notify() call call

May need to use May need to use notifyAll()notifyAll() to to awaken all threads and allow awaken all threads and allow contentioncontention

Page 39: Counting Semaphore Implementation in Java

3.4 Perils of Monitors3.4 Perils of Monitors

sleep()sleep(), , join()join(), and , and wait()wait() throw throw InterruptedExceptionInterruptedException

No exception is thrown if a thread No exception is thrown if a thread is interrupted while blockedis interrupted while blocked

An exception is thrown by An exception is thrown by wait()wait() if if a thread that has been notified is a thread that has been notified is interrupted while waiting to interrupted while waiting to reacquire the monitor lockreacquire the monitor lock

Page 40: Counting Semaphore Implementation in Java

3.4 Perils of Monitors3.4 Perils of Monitors

Ignoring InterruptedException with Ignoring InterruptedException with an empty catch block can be an empty catch block can be acceptable in a while loopacceptable in a while loop

while ( !condition )while ( !condition )

try { wait(); }try { wait(); }

catch (InterruptedException e) {}catch (InterruptedException e) {} Must be using notifyAll()Must be using notifyAll()

Page 41: Counting Semaphore Implementation in Java

3.4 Perils of Monitors3.4 Perils of Monitors

Cannot ignore InterruptedException Cannot ignore InterruptedException when using an if constructwhen using an if construct

if ( !condition )if ( !condition )

try { wait(); }try { wait(); }

catch (InterruptedException e) {}catch (InterruptedException e) {}

Notification slipNotification slip

Page 42: Counting Semaphore Implementation in Java

3.4 Perils of Monitors3.4 Perils of Monitors

It is desirable to have the containing It is desirable to have the containing method throw the exception back to method throw the exception back to the calling function so that the the calling function so that the calling function knows that an calling function knows that an exception has actually occurredexception has actually occurred

Page 43: Counting Semaphore Implementation in Java

4 Counting Semaphores4 Counting Semaphores

V()V() operation operationif threads blocked in P(), unblock if threads blocked in P(), unblock

oneone

else increment semaphore valueelse increment semaphore value P()P() operation operation

if semaphore value is 0 block if semaphore value is 0 block semaphoresemaphore

else decrement semaphore valueelse decrement semaphore value

Page 44: Counting Semaphore Implementation in Java

4 Counting Semaphores4 Counting Semaphores

SafetySafety LivenessLiveness BargingBarging SignalingSignaling Exception propagationException propagation

Page 45: Counting Semaphore Implementation in Java

4.1 First Attempt4.1 First Attempt

public class CountingSemaphorepublic class CountingSemaphore

{{ private int value = 0;private int value = 0;

public CountingSemaphore(int initial)public CountingSemaphore(int initial)

{{ if ( initial > 0 )if ( initial > 0 )

value = initial;value = initial;

}}

Page 46: Counting Semaphore Implementation in Java

4.1 First Attempt4.1 First Attempt

public synchronized void P()public synchronized void P()

throws InterruptedExceptionthrows InterruptedException

{{ if ( value = = 0 )if ( value = = 0 )

wait();wait();

value--;value--;

}}

Page 47: Counting Semaphore Implementation in Java

4.1 First Attempt4.1 First Attempt

public synchronized void V()public synchronized void V()

{{ if (value = = 0)if (value = = 0)

notify();notify();

value++;value++;

}}

}} // End of class CountingSemaphore// End of class CountingSemaphore

Page 48: Counting Semaphore Implementation in Java

4.2 Second Attempt4.2 Second Attempt

public synchronized void P()public synchronized void P()

throws InterruptedExceptionthrows InterruptedException

{{ while ( value = = 0 )while ( value = = 0 )

wait();wait();

value--;value--;

}}

Page 49: Counting Semaphore Implementation in Java

4.3 Third Attempt4.3 Third Attempt

public synchronized void P()public synchronized void P()

throws InterruptedExceptionthrows InterruptedException

{{ value--; value--;

if ( value < 0 )if ( value < 0 )

wait();wait();

}}

Page 50: Counting Semaphore Implementation in Java

4.3 Third Attempt4.3 Third Attempt

public synchronized void V()public synchronized void V()

{{ value++; value++;

if ( value <= 0 )if ( value <= 0 )

notify();notify();

}}

Page 51: Counting Semaphore Implementation in Java

4.4 Fourth Attempt4.4 Fourth Attempt

public class CountingSemaphorepublic class CountingSemaphore

{{ private int value = 0;private int value = 0;

private int waitCount = 0;private int waitCount = 0;

public CountingSemaphore(int initial)public CountingSemaphore(int initial)

{{ if ( initial > 0 )if ( initial > 0 )value = initial;value = initial;

}}

Page 52: Counting Semaphore Implementation in Java

4.4 Fourth Attempt4.4 Fourth Attempt

public synchronized void P() throws IEpublic synchronized void P() throws IE{{ if ( value = = 0 || waitCount > 0 )if ( value = = 0 || waitCount > 0 )

{{ waitCount++;waitCount++;trytry {{ wait();wait(); }}catch(IE e)catch(IE e){{ notify();notify();throw e;throw e; }}finallyfinally {{ waitCount--;waitCount--; }}}}value--;value--;

}}

Page 53: Counting Semaphore Implementation in Java

4.4 Fourth Attempt4.4 Fourth Attempt

public synchronized void V()public synchronized void V()

{{ value++;value++;

if ( waitCount > 0 )if ( waitCount > 0 )

notify();notify();

}}

Page 54: Counting Semaphore Implementation in Java

4.5 Fifth Attempt4.5 Fifth Attempt

public class CountingSemaphorepublic class CountingSemaphore{{ private int value = 0;private int value = 0;private int waitCount = 0;private int waitCount = 0;private boolean notified = false;private boolean notified = false;

public CountingSemaphore(int initial)public CountingSemaphore(int initial){{ if ( initial > 0 )if ( initial > 0 )

value = initial;value = initial;}}

Page 55: Counting Semaphore Implementation in Java

4.5 Fifth Attempt4.5 Fifth Attempt

public synchronized void P() throws IEpublic synchronized void P() throws IE{{ if ( value = = 0 || waitCount > 0 )if ( value = = 0 || waitCount > 0 ){{ waitCount++;waitCount++;trytry{{ dodo { wait(); }{ wait(); }while ( !notified );while ( !notified ); }}// catch and finally unchanged// catch and finally unchangednotified = false;notified = false;}}value--;value--;}}

Page 56: Counting Semaphore Implementation in Java

4.5 Fifth Attempt4.5 Fifth Attempt

public synchronized void V()public synchronized void V()

{{ value++;value++;

if ( waitCount > 0 )if ( waitCount > 0 )

{{ notified = true;notified = true;

notify();notify(); }}

}}

Page 57: Counting Semaphore Implementation in Java

4.6 Sixth Attempt4.6 Sixth Attempt

public class CountingSemaphorepublic class CountingSemaphore{{ private int value = 0;private int value = 0;private int waitCount = 0;private int waitCount = 0;private int notifyCount = 0;private int notifyCount = 0;

public CountingSemaphore(int initial)public CountingSemaphore(int initial){{ if ( initial > 0 )if ( initial > 0 )

value = initial;value = initial;}}

Page 58: Counting Semaphore Implementation in Java

4.6 Sixth Attempt4.6 Sixth Attempt

public synchronized void P() throws IEpublic synchronized void P() throws IE{{ if ( value = = 0 || waitCount > 0 )if ( value = = 0 || waitCount > 0 )

{{ waitCount++;waitCount++;trytry{{ dodo { wait(); }{ wait(); }

while (notifyCount = = 0);while (notifyCount = = 0);}}// catch and finally unchanged// catch and finally unchangednotifyCount--;notifyCount--;

}}value--;value--;

}}

Page 59: Counting Semaphore Implementation in Java

4.6 Sixth Attempt4.6 Sixth Attempt

public synchronized void V()public synchronized void V()

{{ value++;value++;

if ( waitCount > 0 )if ( waitCount > 0 )

{{ notifyCount++;notifyCount++;

notify();notify(); }}

}}

Page 60: Counting Semaphore Implementation in Java

4.7 Seventh Attempt4.7 Seventh Attemptpublic synchronized void P() throws IEpublic synchronized void P() throws IE{{ if ( value < waitCount )if ( value < waitCount )

waitCount++;waitCount++; try{try{ do{wait();}do{wait();} while(notifyCount ==0);while(notifyCount ==0); }catch(InterruptedException e){}catch(InterruptedException e){ notify();notify(); throw e;throw e; }finally{waitCount--}}finally{waitCount--} notifyCount--;notifyCount--; } }

// if block remains unchanged// if block remains unchangedelseelse{{ if ( notifyCount > waitCount )if ( notifyCount > waitCount )

notifyCount--;notifyCount--; }}value--;value--;

}}

Page 61: Counting Semaphore Implementation in Java

4.7 Seventh Attempt4.7 Seventh Attempt

public synchronized void V()public synchronized void V()

{{ value++;value++;

if ( waitCount > notifyCount )if ( waitCount > notifyCount )

{{ notifyCount++;notifyCount++;

notify();notify(); }}

}}

Page 62: Counting Semaphore Implementation in Java

5 Conclusions5 Conclusions

It is difficult to write correct, It is difficult to write correct, synchronized, multithreaded synchronized, multithreaded Java applicationsJava applications

Java monitors are very low-Java monitors are very low-level synchronization toolslevel synchronization tools

Java needs class libraries that Java needs class libraries that provide user-friendly provide user-friendly synchronization toolssynchronization tools

Page 63: Counting Semaphore Implementation in Java

6 Selected References6 Selected References

Andrews, G.RAndrews, G.R. Concurrent . Concurrent Programming: Principles and Programming: Principles and Practice.Practice. Benjamin/Cummings, Benjamin/Cummings, 1991.1991.

Lea, D. Personal communications.Lea, D. Personal communications.

The Java Language Specification The Java Language Specification Gosling,J,Joy,B,and Steele,G Gosling,J,Joy,B,and Steele,G Addison-Wesley 1996 Addison-Wesley 1996

Page 64: Counting Semaphore Implementation in Java

7 Reactions7 Reactions

Java languageJava language CountingSemaphore classCountingSemaphore class ConclusionsConclusions ReferencesReferences