Top Banner
Java ReentrantLock (Part 3) Douglas C. Schmidt [email protected] www.dre.vanderbilt.edu/~schmidt Institute for Software Integrated Systems Vanderbilt University Nashville, Tennessee, USA
37

Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue

Jan 26, 2020

Download

Documents

dariahiddleston
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

Java ReentrantLock(Part 3)

Douglas C. [email protected]

www.dre.vanderbilt.edu/~schmidt

Institute for Software Integrated Systems

Vanderbilt University Nashville, Tennessee, USA

Page 2: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

2

Learning Objectives in this Part of the Lesson• Understand how the concept of mutual

exclusion in concurrent programs• Recognize how Java ReentrantLock

provides mutual exclusion to concurrent programs

• Know how to use ReentrantLockin Java programs

Page 3: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

3

Using ReentrantLock in Java

Page 4: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

4

• ArrayBlockingQueue is a blocking bounded FIFO queue

See docs.oracle.com/javase/8/docs/api/java/util/concurrent/ArrayBlockingQueue.html

Using ReentrantLock in Javapublic class ArrayBlockingQueue<E>

extends AbstractQueue<E>implements BlockingQueue<E>,

java.io.Serializable {

Page 5: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

5

• ArrayBlockingQueue is a blocking bounded FIFO queue

public class ArrayBlockingQueue<E> extends AbstractQueue<E>

implements BlockingQueue<E>, java.io.Serializable {

...

Using ReentrantLock in Java

See docs.oracle.com/javase/8/docs/api/java/util/AbstractQueue.html

Page 6: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

6

• ArrayBlockingQueue is a blocking bounded FIFO queue

public class ArrayBlockingQueue<E> extends AbstractQueue<E>

implements BlockingQueue<E>, java.io.Serializable {

...

Using ReentrantLock in Java

See docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html

Page 7: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

7

• ArrayBlockingQueue is a blocking bounded FIFO queue

public class ArrayBlockingQueue<E> extends AbstractQueue<E>

implements BlockingQueue<E>, java.io.Serializable {

...

Using ReentrantLock in Java

We’ll consider both the interface & implementation of ArrayBlockingQueue

Page 8: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

8

• ArrayBlockingQueue is a blocking bounded FIFO queue

public class ArrayBlockingQueue<E> extends AbstractQueue<E>

implements BlockingQueue<E>, java.io.Serializable {

...// Main lock guarding all accessfinal ReentrantLock lock;...// The queued itemsfinal Object[] items;

// items indices for next take // or put calls int takeIndex;int putIndex;

// Number of elements in the queueint count;

Using ReentrantLock in Java

ReentrantLock used in lieu of Java’s built-in monitor

objects due to their limitations

See www.dre.vanderbilt.edu/~schmidt/C++2java.html#concurrency

Page 9: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

9

• ArrayBlockingQueue is a blocking bounded FIFO queue

public class ArrayBlockingQueue<E> extends AbstractQueue<E>

implements BlockingQueue<E>, java.io.Serializable {

...// Main lock guarding all accessfinal ReentrantLock lock;...// The queued itemsfinal Object[] items;

// items indices for next take // or put calls int takeIndex;int putIndex;

// Number of elements in the queueint count;

Using ReentrantLock in Java

Object state that’s being protected by the lock

Page 10: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

10

• ArrayBlockingQueue is a blocking bounded FIFO queue

public class ArrayBlockingQueue<E> extends AbstractQueue<E>

implements BlockingQueue<E>, java.io.Serializable {

...// Main lock guarding all accessfinal ReentrantLock lock;...// The queued itemsfinal Object[] items;

// items indices for next take // or put calls int takeIndex;int putIndex;

// Number of elements in the queueint count;

See docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Lock.html

Using ReentrantLock in Java

Fields needn’t be defined as volatile since ReentrantLockhandles all of the atomicity, visibility, & ordering issues

Page 11: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

11

T1

unlocked(holdCount = 0)

ArrayBlockingQueue

ArrayBlockingQueue<String> q = new ArrayBlockingQueue<String>(10);

...// Called by thread T1String s = q.take();...

Critical Section

• ArrayBlockingQueue is a blocking bounded FIFO queue

Using ReentrantLock in Java

Thread T1 acquires the lock & enters the critical section

Page 12: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

12

unlocked(holdCount = 0)

ArrayBlockingQueue

Critical Section

locked(holdCount = 1)

lock()

• ArrayBlockingQueue is a blocking bounded FIFO queue

public class ArrayBlockingQueue<E> extends AbstractQueue<E>

implements BlockingQueue<E>, java.io.Serializable {

...public E take() ... {final ReentrantLock lock = this.lock;

lock.lockInterruptibly();...

Using ReentrantLock in Java

The lock’s hold count is incremented by 1

T1

Page 13: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

13

...// Called by thread T2String s = q.take();...

Using ReentrantLock in Java

ArrayBlockingQueue

• ArrayBlockingQueue is a blocking bounded FIFO queue

unlocked(holdCount = 0)

Critical Section

locked(holdCount = 1)

T2

A call to take() from thread T2 will block until

thread T1 is finished

T1

Page 14: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

14

unlocked(holdCount = 0)

ArrayBlockingQueue

Critical Section

locked(holdCount = 1)

T2

unlock()

• ArrayBlockingQueue is a blocking bounded FIFO queue

public class ArrayBlockingQueue<E> extends AbstractQueue<E>

implements BlockingQueue<E>, java.io.Serializable {

...public E take() ... {final ReentrantLock lock = this.lock;

lock.lockInterruptibly();try { ... } finally { lock.unlock();

}...

Using ReentrantLock in Java

When thread T1 finishes in take() it unlocks the lock

T1

Page 15: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

15

unlocked(holdCount = 0)

ArrayBlockingQueue

Critical Section

locked(holdCount = 1)

T2

• ArrayBlockingQueue is a blocking bounded FIFO queue

public class ArrayBlockingQueue<E> extends AbstractQueue<E>

implements BlockingQueue<E>, java.io.Serializable {

...public E take() ... {final ReentrantLock lock = this.lock;

lock.lockInterruptibly();try { ... } finally { lock.unlock();

}...

Using ReentrantLock in Java

unlock()

At this point holdCountreverts back to 0

T1

Page 16: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

16

unlocked(holdCount = 0)

ArrayBlockingQueue

Critical Section

locked(holdCount = 1)

• ArrayBlockingQueue is a blocking bounded FIFO queue

public class ArrayBlockingQueue<E> extends AbstractQueue<E>

implements BlockingQueue<E>, java.io.Serializable {

...public E take() ... {final ReentrantLock lock = this.lock;

lock.lockInterruptibly();try { ... } finally { lock.unlock();

}...

Using ReentrantLock in Java

See tutorials.jenkov.com/java-concurrency/locks.html#finally

Ensure lock is always released when T1 exits

the critical section

unlock()

T1

Page 17: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

17

unlocked(holdCount = 0)

ArrayBlockingQueue

Critical Section

locked(holdCount = 1)

T2

lock()

• ArrayBlockingQueue is a blocking bounded FIFO queue

public class ArrayBlockingQueue<E> extends AbstractQueue<E>

implements BlockingQueue<E>, java.io.Serializable {

...public E take() ... {final ReentrantLock lock = this.lock;

lock.lockInterruptibly();...

Using ReentrantLock in Java

Thread T2 can now enter the critical section of take() & start running

Page 18: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

18

• ArrayBlockingQueue needs touse more than ReentrantLockto implement its semantics

public class ArrayBlockingQueue<E> extends AbstractQueue<E>

implements BlockingQueue<E>, java.io.Serializable {

...public E take() ... {final ReentrantLock lock = this.lock;

lock.lockInterruptibly();try {while (count == 0)notEmpty.await();

return extract();} finally {lock.unlock();

}}

Upcoming lesson on “Java ConditionObject” shows more on ArrayBlockingQueue

Critical Section

ArrayBlockingQueue

T1

lock

notEmptynotFull

Using ReentrantLock in Java

A Java ConditionObject is used to coordinate multiple threads

Page 19: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

19

• ArrayBlockingQueue needs touse more than ReentrantLockto implement its semantics

public class ArrayBlockingQueue<E> extends AbstractQueue<E>

implements BlockingQueue<E>, java.io.Serializable {

...public E take() ... {final ReentrantLock lock = this.lock;

lock.lockInterruptibly();try {while (count == 0)notEmpty.await();

return extract();} finally {lock.unlock();

}}Critical

Section

ArrayBlockingQueue T1

lock

notEmptynotFull

See en.wikipedia.org/wiki/Guarded_suspension & www.dre.vanderbilt.edu/~schmidt/PDF/monitor.pdf

Using ReentrantLock in Java

These mechanisms implement Guarded Suspension & Monitor Object patterns

Page 20: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

20

End of Java ReentrantLock(Part 3)

Page 21: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

Java ReentrantLock(Part 4)

Douglas C. [email protected]

www.dre.vanderbilt.edu/~schmidt

Institute for Software Integrated Systems

Vanderbilt University Nashville, Tennessee, USA

Page 22: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

2

Learning Objectives in this Part of the Lesson• Understand how the concept of mutual

exclusion in concurrent programs• Recognize how Java ReentrantLock

provides mutual exclusion to concurrent programs

• Know how to use ReentrantLockin Java programs

• Appreciate Java ReentrantLockusage considerations

Page 23: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

3

ReentrantLock UsageConsiderations

Page 24: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

4

• ReentrantLock must be used via a “fully bracketed” protocol

void someMethod() {ReentrantLock lock = this.lock;

lock.lock();try { ... } finally { lock.unlock();

}}

ReentrantLock Usage Considerations

The thread that acquires the lock must be the one to release it

Page 25: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

5

• ReentrantLock must be used via a “fully bracketed” protocol• This design is known as

the “Scoped Locking” pattern

ReentrantLock Usage Considerations

See www.dre.vanderbilt.edu/~schmidt/PDF/locking-patterns.pdf

void someMethod() {ReentrantLock lock = this.lock;

lock.lock();try { ... } finally { lock.unlock();

}}

The finally clause ensures that the lock is released on all paths out the try clause

Page 26: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

6

• ReentrantLock must be used via a “fully bracketed” protocol• This design is known as

the “Scoped Locking” pattern• Implemented implicitly via

Java synchronized methods & statements

ReentrantLock Usage Considerationsvoid someMethod() {synchronized (this) {...

}}

See lesson on “Java Built-in Monitor Object”

Page 27: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

7

• ReentrantLock must be used via a “fully bracketed” protocol• This design is known as

the “Scoped Locking” pattern• Implemented implicitly via

Java synchronized methods & statements

• This pattern is commonly usedin C++ (& C#) via constructors & destructors

void write_to_file(std::ofstream &file,const std::string &msg)

{static std::mutex mutex;

std::lock_guard<std::mutex> lock(mutex);

file << msg << std::endl;}

ReentrantLock Usage Considerations

See en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization

Page 28: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

8

• ReentrantLock supports “recursive mutex” semantics where a lock may be acquired multiple times by the same thread, without causing self-deadlock

ReentrantLock Usage Considerations

See en.wikipedia.org/wiki/Reentrant_mutex

Page 29: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

9See github.com/douglascraigschmidt/LiveLessons/tree/master/Java8/ex24

• ReentrantLock semantics are useful for frameworks that hold locks during callbacks to user code

cDTimer: CountDownTimer

start()

onTick()

onFinish()

timerHandler

run()

cancel()

mLock.lock();try {mCancelled = true;mSchedExeSvc

.shutdownNow();} finally {mLock.unlock();

}mLock.lock();try {

...onTick(millisLeft);...

} finally {mLock.unlock();

}

if (...)cancel();

onTick() is called with the mLock held

mLock

ReentrantLock Usage Considerations

Page 30: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

10See github.com/douglascraigschmidt/LiveLessons/tree/master/Java8/ex24

• ReentrantLock semantics are useful for frameworks that hold locks during callbacks to user code

cDTimer: CountDownTimer

start()

onTick()

onFinish()

timerHandler

run()

cancel()

mLock.lock();try {mCancelled = true;mSchedExeSvc

.shutdownNow();} finally {mLock.unlock();

}mLock.lock();try {

...onTick(millisLeft);...

} finally {mLock.unlock();

}

if (...)cancel();

onTick() can call cancel

mLock

ReentrantLock Usage Considerations

Page 31: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

11See github.com/douglascraigschmidt/LiveLessons/tree/master/Java8/ex24

• ReentrantLock semantics are useful for frameworks that hold locks during callbacks to user code

cDTimer: CountDownTimer

start()

onTick()

onFinish()

timerHandler

run()

cancel()

mLock.lock();try {mCancelled = true;mSchedExeSvc

.shutdownNow();} finally {mLock.unlock();

}mLock.lock();try {

...onTick(millisLeft);...

} finally {mLock.unlock();

}

if (...)cancel();

cancel() also acquires mLock, so it must be recursive or self-deadlock will occur

mLock

ReentrantLock Usage Considerations

Page 32: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

12

• ReentrantLocks can be tedious & error-prone to program due to common traps & pitfalls

ReentrantLock Usage Considerations

Page 33: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

13

• ReentrantLocks can be tedious & error-prone to program due to common traps & pitfalls, e.g.• Holding a lock for a long

time without needing it

ReentrantLock Usage Considerationsvoid someMethod() {ReentrantLock lock = this.lock;

lock.lock();try { for (;;) {// Do something that // doesn’t involve lock

} } finally { lock.unlock();

}}

Page 34: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

14

• ReentrantLocks can be tedious & error-prone to program due to common traps & pitfalls, e.g.• Holding a lock for a long

time without needing it• Acquiring a lock &

forgetting to release it

ReentrantLock Usage Considerationsvoid someMethod() {ReentrantLock lock = this.lock;

lock.lock();... // Critical sectionreturn;

}

Page 35: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

15

• ReentrantLocks can be tedious & error-prone to program due to common traps & pitfalls, e.g.• Holding a lock for a long

time without needing it• Acquiring a lock &

forgetting to release it• Releasing a lock that was

never acquired• or has already been

released

ReentrantLock Usage Considerationsvoid someMethod() {ReentrantLock lock = this.lock;

// lock.lock();try { ... // Critical section

} finally { lock.unlock();

}}

Page 36: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

16

• ReentrantLocks can be tedious & error-prone to program due to common traps & pitfalls, e.g.• Holding a lock for a long

time without needing it• Acquiring a lock &

forgetting to release it• Releasing a lock that was

never acquired• Accessing a resource without

acquiring a lock for it first • or after releasing it

Compare with lesson on “Java Built-in Monitor Objects”

ReentrantLock Usage Considerationsvoid someMethod() {ReentrantLock lock = this.lock;

// lock.lock();try { ... // Critical section

} finally { // lock.unlock();

}}

Page 37: Java ReentrantLock (Part 3) - Vanderbilt Universityschmidt/cs891s/2018-PDFs/L2-Java...10 • ArrayBlockingQueue is a blocking bounded FIFO queue public class ArrayBlockingQueue<E>

17

End of Java ReentrantLock(Part 4)