lecture 16: thread safety in java - department of … › comp › 150ccp › lectures ›...
TRANSCRIPT
![Page 1: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/1.jpg)
COMP 150-CCPCOMP 150-CCPConcurrent ProgrammingConcurrent Programming
Lecture 16:Thread Safety in Java
Dr. Richard S. Hall [email protected]
Concurrent programming – March 13, 2008
![Page 2: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/2.jpg)
ReferenceReference
The content of this lecture is based on Chapter 2 of the Java Concurrency in Practice book by
Brian Goetz.
![Page 3: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/3.jpg)
Java and ConcurrencyJava and Concurrency
● Threads are everywhere in Java JVM housekeeping (e.g., garbage collection,
finalization) Main thread for running application AWT & Swing threads for events Timer class for deferred tasks Component frameworks such as Servlets and RMI
create pools of threads
● In Java your application is likely to be multi-threaded whether you know it or not
Thus, you have to be familiar with concurrency and thread safety
![Page 4: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/4.jpg)
State ManagementState Management
● Concurrent programming is not really about threads or locks, these are simply mechanisms
● At its core, it is about managing access to state, particularly shared, mutable state
In Java, this state is the data fields of objects An object's state encompasses any data that can affect
its externally visible behavior
![Page 5: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/5.jpg)
Need for Thread SafetyNeed for Thread Safety
● Depends on whether object will be accessed from multiple threads
This is a property of how the object will be used, not what it does
● If multiple threads can access an object and one of them might write to it, then they all must coordinate access using synchronization
There are no special situations where this rule does not apply
![Page 6: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/6.jpg)
Achieving Thread SafetyAchieving Thread Safety
● If multiple threads access the same mutable state variable without appropriate synchronization, then your program is broken
![Page 7: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/7.jpg)
Achieving Thread SafetyAchieving Thread Safety
● If multiple threads access the same mutable state variable without appropriate synchronization, then your program is broken
● There are three ways to fix it Don't share the state variable across threads Make the state variable immutable Use synchronization whenever accessing the state
variable
![Page 8: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/8.jpg)
Achieving Thread SafetyAchieving Thread Safety
● If multiple threads access the same mutable state variable without appropriate synchronization, then your program is broken
● There are three ways to fix it Don't share the state variable across threads Make the state variable immutable Use synchronization whenever accessing the state
variable
● None of these are necessarily as easy as they may sound
![Page 9: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/9.jpg)
Thread-Safe ClassesThread-Safe Classes
● A class is thread safe when it continues to behave correctly when accessed from multiple threads
![Page 10: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/10.jpg)
Thread-Safe ClassesThread-Safe Classes
● A class is thread safe when it continues to behave correctly when accessed from multiple threads
Regardless of scheduling or interleaving of execution
![Page 11: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/11.jpg)
Thread-Safe ClassesThread-Safe Classes
● A class is thread safe when it continues to behave correctly when accessed from multiple threads
Regardless of scheduling or interleaving of execution No set of operations performed sequentially or
concurrently on instances of thread-safe classes can cause an instance to be in an invalid state
![Page 12: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/12.jpg)
Thread-Safe ClassesThread-Safe Classes
● A class is thread safe when it continues to behave correctly when accessed from multiple threads
Regardless of scheduling or interleaving of execution No set of operations performed sequentially or
concurrently on instances of thread-safe classes can cause an instance to be in an invalid state
Any needed synchronization is encapsulated in the class so that clients need not provide their own
▴ The concept of a thread-safe class only makes sense if the class fully encapsulates its state
Likewise for the entire body of code that comprises a thread-safe program
![Page 13: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/13.jpg)
Thread-Safe Class vs ProgramThread-Safe Class vs Program
● Is a thread-safe program simply a program constructed of thread-safe classes?
![Page 14: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/14.jpg)
Thread-Safe Class vs ProgramThread-Safe Class vs Program
● Is a thread-safe program simply a program constructed of thread-safe classes?
No▴ All thread-safe classes can still result in non-thread-safe
programs▴ A thread-safe program may use non-thread-safe classes
![Page 15: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/15.jpg)
Thread-Safety ExampleThread-Safety Example
public class StatelessFactorizer implements Servlet { public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = factor(i); encodeIntoResponse(resp, factors); }}
● Stateless factorizing servlet
![Page 16: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/16.jpg)
Thread-Safety ExampleThread-Safety Example
public class StatelessFactorizer implements Servlet { public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = factor(i); encodeIntoResponse(resp, factors); }}
● Stateless factorizing servlet
Has no fields and refer-ences no fields from other classes; everything is on the stack. Therefore, it is
thread safe.
![Page 17: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/17.jpg)
Thread-Safety ExampleThread-Safety Example
public class StatelessFactorizer implements Servlet { public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = factor(i); encodeIntoResponse(resp, factors); }}
● Stateless factorizing servlet
Stateless objects are al-ways thread safe.
![Page 18: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/18.jpg)
Thread-Safety ExampleThread-Safety Example
public class CountingFactorizer implements Servlet { private long count = 0;
public long getCount() { return count; }
public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = factor(i); ++count; encodeIntoResponse(resp, factors); }}
● Stateful factorizing servlet Keeps track of how many times it has been invoked
![Page 19: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/19.jpg)
Thread-Safety ExampleThread-Safety Example
public class CountingFactorizer implements Servlet { private long count = 0;
public long getCount() { return count; }
public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = factor(i); ++count; encodeIntoResponse(resp, factors); }}
● Stateful factorizing servlet Keeps track of how many times it has been invoked
This would work fine with in a single-threaded pro-gram, but not in a multi-threaded one...this is sus-ceptible to lost updates.
![Page 20: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/20.jpg)
Thread-Safety ExampleThread-Safety Example
public class CountingFactorizer implements Servlet { private long count = 0;
public long getCount() { return count; }
public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = factor(i); ++count; encodeIntoResponse(resp, factors); }}
● Stateful factorizing servlet Keeps track of how many times it has been invoked
This is a read-modify-write race condition.
![Page 21: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/21.jpg)
Race ConditionsRace Conditions
● A race condition is the possibility of incorrect results due to timing of execution
![Page 22: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/22.jpg)
Race ConditionsRace Conditions
● A race condition is the possibility of incorrect results due to timing of execution
● Most common form is check-then-act A stale observation is used to determine what to do
next▴ We've seen this in our homework where we have used
individually atomic actions to test and the perform some action
![Page 23: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/23.jpg)
Race ConditionsRace Conditions
● A race condition is the possibility of incorrect results due to timing of execution
● Most common form is check-then-act A stale observation is used to determine what to do
next▴ We've seen this in our homework where we have used
individually atomic actions to test and the perform some action
● Similar to what happens in real-life if you try to meet someone...
Need to have some agreed upon protocol
![Page 24: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/24.jpg)
Race Condition ExampleRace Condition Example
public class LazyInit { private ExpensiveObject instance = null;
public ExpensiveObject getInstance() { if (instance == null) instance = new ExpensiveObject(); return instance; }}
● Lazy initialization
![Page 25: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/25.jpg)
Race Condition ExampleRace Condition Example
public class LazyInit { private ExpensiveObject instance = null;
public ExpensiveObject getInstance() { if (instance == null) instance = new ExpensiveObject(); return instance; }}
● Lazy initialization
Unfortunate timing could result in this method re-
turning different in-stances.
![Page 26: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/26.jpg)
Compound ActionsCompound Actions
● Read-modify-write and check-then-act operation sequences are compound actions
To ensure thread safety, all constituent actions must be performed atomically
● An operation or sequence of operations is atomic if it is indivisible relative to other operations on the same state
i.e., other threads see it as either happening completely or not at all.
![Page 27: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/27.jpg)
Thread-Safety ExampleThread-Safety Example
public class CountingFactorizer implements Servlet { private final AtomicLong count = new AtomicLong(0);
public long getCount() { return count.get(); }
public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = factor(i); count.incrementAndGet(); encodeIntoResponse(resp, factors); }}
● Modified stateful factorizing servlet Keeps track of how many times it has been invoked
![Page 28: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/28.jpg)
Thread-Safety ExampleThread-Safety Example
public class CountingFactorizer implements Servlet { private final AtomicLong count = new AtomicLong(0);
public long getCount() { return count.get(); }
public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = factor(i); count.incrementAndGet(); encodeIntoResponse(resp, factors); }}
● Modified stateful factorizing servlet Keeps track of how many times it has been invoked
Since this uses a thread-safeAtomicLong type from
java.util.concurrent.atomic, the class is once again thread safe.
![Page 29: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/29.jpg)
Thread-Safety ExampleThread-Safety Example
public class CountingFactorizer implements Servlet { private final AtomicLong count = new AtomicLong(0);
public long getCount() { return count.get(); }
public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = factor(i); count.incrementAndGet(); encodeIntoResponse(resp, factors); }}
● Modified stateful factorizing servlet Keeps track of how many times it has been invoked
AtomicLong provides an atomic read-modify-
write operation for incre-menting the value.
![Page 30: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/30.jpg)
Thread-Safety ExampleThread-Safety Example
public class CountingFactorizer implements Servlet { private final AtomicLong count = new AtomicLong(0);
public long getCount() { return count.get(); }
public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = factor(i); count.incrementAndGet(); encodeIntoResponse(resp, factors); }}
● Modified stateful factorizing servlet Keeps track of how many times it has been invoked
Advice:Where practical, use exist-ing thread-safe objects to
manage your state.
![Page 31: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/31.jpg)
Side Note: AtomicLongSide Note: AtomicLong
● AtomicLong replaces a long/Long get() - Gets the current value.
set(long newValue) - Sets to the given value.
lazySet(long newValue) - Eventually sets to the given value.
compareAndSet(long expect, long update) - Atomically sets the value to the given updated value if the current value == the expected value.
weakCompareAndSet(long expect, long update) - Atomically sets the value to the given updated value if the current value == the expected value.
getAndAdd(long delta) - Atomically adds the given value to the current value.
getAndDecrement() - Atomically decrements by one the current value.
getAndIncrement() - Atomically increments by one the current value.
getAndSet(long newValue) - Atomically sets to the given value and returns the old value.
addAndGet(long delta) - Atomically adds the given value to the current value.
incrementAndGet() - Atomically increments by one the current value.
decrementAndGet() - Atomically decrements by one the current value.
![Page 32: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/32.jpg)
Thread-Safety ExampleThread-Safety Example
public class CachingFactorizer implements Servlet { private final AtomicReference<BigInteger> lastNumber = new AtomicReference<BigInteger>(); private final AtomicReference<BigInteger[]> lastFactors = new AtomicReference<BigInteger[]>();
public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); if (i.equals(lastNumber.get())) encodeIntoResponse(resp, lastFactors.get()); else { BigInteger[] factors = factor(i); lastNumber.set(i); lastFactors.set(factors); encodeIntoResponse(resp, factors); } }}
● Caching factorizing servlet Remembers last result
![Page 33: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/33.jpg)
Thread-Safety ExampleThread-Safety Example
public class CachingFactorizer implements Servlet { private final AtomicReference<BigInteger> lastNumber = new AtomicReference<BigInteger>(); private final AtomicReference<BigInteger[]> lastFactors = new AtomicReference<BigInteger[]>();
public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); if (i.equals(lastNumber.get())) encodeIntoResponse(resp, lastFactors.get()); else { BigInteger[] factors = factor(i); lastNumber.set(i); lastFactors.set(factors); encodeIntoResponse(resp, factors); } }}
● Caching factorizing servlet Remembers last result
Even though our two references are atomic,
they are not independent.
![Page 34: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/34.jpg)
Thread-Safety ExampleThread-Safety Example
public class CachingFactorizer implements Servlet { private final AtomicReference<BigInteger> lastNumber = new AtomicReference<BigInteger>(); private final AtomicReference<BigInteger[]> lastFactors = new AtomicReference<BigInteger[]>();
public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); if (i.equals(lastNumber.get())) encodeIntoResponse(resp, lastFactors.get()); else { BigInteger[] factors = factor(i); lastNumber.set(i); lastFactors.set(factors); encodeIntoResponse(resp, factors); } }}
● Caching factorizing servlet Remembers last result
Thus, dependent opera-tions on them must be
done atomically...
![Page 35: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/35.jpg)
Thread-Safety ExampleThread-Safety Example
public class CachingFactorizer implements Servlet { private final AtomicReference<BigInteger> lastNumber = new AtomicReference<BigInteger>(); private final AtomicReference<BigInteger[]> lastFactors = new AtomicReference<BigInteger[]>();
public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); if (i.equals(lastNumber.get())) encodeIntoResponse(resp, lastFactors.get()); else { BigInteger[] factors = factor(i); lastNumber.set(i); lastFactors.set(factors); encodeIntoResponse(resp, factors); } }}
● Caching factorizing servlet Remembers last result
And here too.
![Page 36: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/36.jpg)
Thread-Safety ExampleThread-Safety Example
public class CachingFactorizer implements Servlet { private final AtomicReference<BigInteger> lastNumber = new AtomicReference<BigInteger>(); private final AtomicReference<BigInteger[]> lastFactors = new AtomicReference<BigInteger[]>();
public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); if (i.equals(lastNumber.get())) encodeIntoResponse(resp, lastFactors.get()); else { BigInteger[] factors = factor(i); lastNumber.set(i); lastFactors.set(factors); encodeIntoResponse(resp, factors); } }}
● Caching factorizing servlet Remembers last result
Thus, this class is not thread safe.
![Page 37: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/37.jpg)
Side Note: AtomicReference<V>Side Note: AtomicReference<V>
● AtomicReference<V> can be used in place of a reference to an object
get() - Gets the current value.
set(V newValue) - Sets to the given value.
lazySet(V newValue) - Eventually sets to the given value.
getAndSet(V newValue) - Atomically sets to the given value and returns the old value.
compareAndSet(V expect, V update) - Atomically sets the value to the given updated value if the current value == the expected value.
weakCompareAndSet(V expect, V update) - Atomically sets the value to the given updated value if the current value == the expected value.
![Page 38: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/38.jpg)
Intrinsic LocksIntrinsic Locks
● Java offers built-in locking to enforce atomicity via the synchronized block
One lock associated with each object instance A synchronized block is comprised of
▴ An object reference that is used as the lock▴ A block of code that is guarded by the lock
Only one thread at any given time can be inside of a block guarded by a given lock (i.e, mutual exclusion)
▴ The lock is acquired/released by the thread on entry/exit It may be blocked to wait to acquire the lock
Although each object has a lock, that lock can be used for any purpose
▴ Not necessarily related to the object itself▴ Possibly spanning many objects
![Page 39: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/39.jpg)
Intrinsic LocksIntrinsic Locks
● A lock associated with an object does not restrict access to the object's state
It only restricts multiple threads from acquiring the lock at the same time
Having a built-in object lock is only a convenience so that we don't have to explicitly create locks
● Encapsulation with an appropriate locking protocol is the only way to restrict access to an object's state
![Page 40: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/40.jpg)
Intrinsic LocksIntrinsic Locks
public class Foo { public synchronized void bar() { ... }}
Is equivalent to:
public class Foo { public void bar() { synchronized (this) { ... } }}
![Page 41: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/41.jpg)
Intrinsic LocksIntrinsic Locks
public class Foo { public synchronized void bar() { ... }}
Is equivalent to:
public class Foo { public void bar() { synchronized (this) { ... } }}
Why might you do this instead?
![Page 42: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/42.jpg)
Intrinsic LocksIntrinsic Locks
public class Foo { public synchronized void bar() { ... }}
Is equivalent to:
public class Foo { public void bar() { synchronized (this) { ... } }}
To provide more fine-grained locking.
![Page 43: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/43.jpg)
Intrinsic LocksIntrinsic Locks
public class Foo { public synchronized void bar() { ... }
public void woz() { ... }}
● Assuming Foo is thread safe, what can we assume about bar() and woz()?
![Page 44: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/44.jpg)
Intrinsic LocksIntrinsic Locks
public class Foo { public synchronized void bar() { ... }
public void woz() { ... }}
● Assuming Foo is thread safe, what can we assume about bar() and woz()?
Perhaps that the woz() method does not access
shared state...
![Page 45: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/45.jpg)
Intrinsic LocksIntrinsic Locks
public class Foo { public synchronized void bar() { ... }
public void woz() { ... }}
● Assuming Foo is thread safe, what can we assume about bar() and woz()?
Or that woz() has more fine-grained locking...
![Page 46: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/46.jpg)
Intrinsic LocksIntrinsic Locks
public class Foo { public synchronized void bar() { ... }
public void woz() { ... }}
● Assuming Foo is thread safe, what can we assume about bar() and woz()?
At a minimum, we know that more than one
thread can enter woz() and thus the Foo in-
stance at a given time.
![Page 47: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/47.jpg)
Intrinsic LocksIntrinsic Locks
public class Foo { public Foo(String s) { ... } public void foo() { synchronized (s) { ... } }}
public class Bar { public Bar(String s) { ... } public void bar() { synchronized (s) { ... } }}
● How does sharing locks across objects work?
...String s = new String(“l”);Foo f = new Foo(s);Bar b = new Bar(s);...
![Page 48: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/48.jpg)
Intrinsic LocksIntrinsic Locks
public class Foo { public Foo(String s) { ... } public void foo() { synchronized (s) { ... } }}
public class Bar { public Bar(String s) { ... } public void bar() { synchronized (s) { ... } }}
● How does sharing locks across objects work?
...String s = new String(“l”);Foo f = new Foo(s);Bar b = new Bar(s);...
As you would expect, only one thread can be ex-ecuting inside the guarded
code blocks of Foo or Bar at a given time.
![Page 49: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/49.jpg)
Thread-Safety ExampleThread-Safety Example
public class CachingFactorizer implements Servlet { private final AtomicReference<BigInteger> lastNumber = new AtomicReference<BigInteger>(); private final AtomicReference<BigInteger[]> lastFactors = new AtomicReference<BigInteger[]>();
public synchronized void service( ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); if (i.equals(lastNumber.get())) encodeIntoResponse(resp, lastFactors.get()); else { BigInteger[] factors = factor(i); lastNumber.set(i); lastFactors.set(factors); encodeIntoResponse(resp, factors); } }}
● Modified caching factorizing servlet Remembers last result
![Page 50: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/50.jpg)
Thread-Safety ExampleThread-Safety Example
public class CachingFactorizer implements Servlet { private final AtomicReference<BigInteger> lastNumber = new AtomicReference<BigInteger>(); private final AtomicReference<BigInteger[]> lastFactors = new AtomicReference<BigInteger[]>();
public synchronized void service( ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); if (i.equals(lastNumber.get())) encodeIntoResponse(resp, lastFactors.get()); else { BigInteger[] factors = factor(i); lastNumber.set(i); lastFactors.set(factors); encodeIntoResponse(resp, factors); } }}
● Modified caching factorizing servlet Remembers last result
This does achieve thread safety, but it no longer
allows concurrent execu-tion; thus, its perfor-
mance is worse.
![Page 51: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/51.jpg)
Intrinsic LocksIntrinsic Locks
● Would the following code deadlock?
public class Widget { public synchronized void doSomething() { ... }}
public class LoggingWidget extends Widget { public synchronized void doSomething() { System.out.println("Calling doSomething"); super.doSomething(); }}
![Page 52: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/52.jpg)
Intrinsic LocksIntrinsic Locks
● Would the following code deadlock?
public class Widget { public synchronized void doSomething() { ... }}
public class LoggingWidget extends Widget { public synchronized void doSomething() { System.out.println("Calling doSomething"); super.doSomething(); }}
No, because intrinsic locks are reentrant.
![Page 53: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/53.jpg)
Intrinsic LocksIntrinsic Locks
● Intrinsic locks are acquired per thread, not per invocation
Semaphores are acquired per invocation, for example
![Page 54: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/54.jpg)
Intrinsic LocksIntrinsic Locks
● Intrinsic locks are acquired per thread, not per invocation
Semaphores are acquired per invocation, for example
● Essentially, Java remembers the thread that owns a lock and keeps a lock counter
The counter value for unheld locks is zero Each time a given thread acquires a lock, it increments
the counter▴ Likewise, it decrements the counter each time it exits a
synchronized block until it reaches zero and the lock is freed
![Page 55: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/55.jpg)
Intrinsic LocksIntrinsic Locks
● Intrinsic locks are acquired per thread, not per invocation
Semaphores are acquired per invocation, for example
● Essentially, Java remembers the thread that owns a lock and keeps a lock counter
The counter value for unheld locks is zero Each time a given thread acquires a lock, it increments
the counter▴ Likewise, it decrements the counter each time it exits a
synchronized block until it reaches zero and the lock is freed
● Reentrancy facilitates encapsulation of locking behavior and simplifies development object-oriented concurrent code
![Page 56: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/56.jpg)
Locking Rules of ThumbLocking Rules of Thumb
● Compound actions on shared state must be made atomic (i.e., read-modify-write, check-then-act)
![Page 57: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/57.jpg)
Locking Rules of ThumbLocking Rules of Thumb
● Compound actions on shared state must be made atomic (i.e., read-modify-write, check-then-act)
Combining individually atomic actions does not result in an atomic action
![Page 58: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/58.jpg)
Locking Rules of ThumbLocking Rules of Thumb
● Compound actions on shared state must be made atomic (i.e., read-modify-write, check-then-act)
Combining individually atomic actions does not result in an atomic action
● All access to shared state must be synchronized, not just modifications
![Page 59: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/59.jpg)
Locking Rules of ThumbLocking Rules of Thumb
● Compound actions on shared state must be made atomic (i.e., read-modify-write, check-then-act)
Combining individually atomic actions does not result in an atomic action
● All access to shared state must be synchronized, not just modifications
Use same lock wherever a specific variable is accessed▴ Variable is considered to be guarded by the specific lock▴ Also true if multiple variables make up a single invariant
You should clearly document which locks are used to guard which state
![Page 60: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/60.jpg)
Locking Rules of ThumbLocking Rules of Thumb
● Compound actions on shared state must be made atomic (i.e., read-modify-write, check-then-act)
Combining individually atomic actions does not result in an atomic action
● All access to shared state must be synchronized, not just modifications
Use same lock wherever a specific variable is accessed▴ Variable is considered to be guarded by the specific lock▴ Also true if multiple variables make up a single invariant
You should clearly document which locks are used to guard which state
● Only guard mutable state that is potentially accessed by multiple threads
![Page 61: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/61.jpg)
Locking Rules of ThumbLocking Rules of Thumb
● Need right amount of locking
![Page 62: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/62.jpg)
Locking Rules of ThumbLocking Rules of Thumb
● Need right amount of locking Too little could result in invalidate states
![Page 63: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/63.jpg)
Locking Rules of ThumbLocking Rules of Thumb
● Need right amount of locking Too little could result in invalidate states Too much could result in deadlock
![Page 64: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/64.jpg)
Locking Rules of ThumbLocking Rules of Thumb
● Need right amount of locking Too little could result in invalidate states Too much could result in deadlock Too coarse grained could result in poor performance
![Page 65: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/65.jpg)
Locking Rules of ThumbLocking Rules of Thumb
● Need right amount of locking Too little could result in invalidate states Too much could result in deadlock Too coarse grained could result in poor performance Too fine grained increases complexity and could also
result in poor performance
![Page 66: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/66.jpg)
Locking Rules of ThumbLocking Rules of Thumb
● Need right amount of locking Too little could result in invalidate states Too much could result in deadlock Too coarse grained could result in poor performance Too fine grained increases complexity and could also
result in poor performance
● Prefer simplicity over performance Optimize later, if necessary
![Page 67: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/67.jpg)
Locking Rules of ThumbLocking Rules of Thumb
● Need right amount of locking Too little could result in invalidate states Too much could result in deadlock Too coarse grained could result in poor performance Too fine grained increases complexity and could also
result in poor performance
● Prefer simplicity over performance Optimize later, if necessary
● Avoid holding locks during lengthy computations
![Page 68: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/68.jpg)
Locking Rules of ThumbLocking Rules of Thumb
● Need right amount of locking Too little could result in invalidate states Too much could result in deadlock Too coarse grained could result in poor performance Too fine grained increases complexity and could also
result in poor performance
● Prefer simplicity over performance Optimize later, if necessary
● Avoid holding locks during lengthy computations● Avoid calling external code while holding locks
![Page 69: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/69.jpg)
Thread-Safety ExampleThread-Safety Example
@ThreadSafepublic class CachedFactorizer implements Servlet { @GuardedBy("this") private BigInteger lastNumber, lastFactors[]; @GuardedBy("this") private long hits, cacheHits; public synchronized long getHits() { return hits; } public synchronized double getCacheHitRatio() { return (double) cacheHits / (double) hits; } public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = null; synchronized (this) { ++hits; if (i.equals(lastNumber)) { ++cacheHits; factors = lastFactors.clone(); } } if (factors == null) { factors = factor(i); synchronized (this) { lastNumber = i; lastFactors = factors.clone(); } } encodeIntoResponse(resp, factors); }}
![Page 70: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/70.jpg)
Thread-Safety ExampleThread-Safety Example
@ThreadSafepublic class CachedFactorizer implements Servlet { @GuardedBy("this") private BigInteger lastNumber, lastFactors[]; @GuardedBy("this") private long hits, cacheHits; public synchronized long getHits() { return hits; } public synchronized double getCacheHitRatio() { return (double) cacheHits / (double) hits; } public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = null; synchronized (this) { ++hits; if (i.equals(lastNumber)) { ++cacheHits; factors = lastFactors.clone(); } } if (factors == null) { factors = factor(i); synchronized (this) { lastNumber = i; lastFactors = factors.clone(); } } encodeIntoResponse(resp, factors); }}
Is this class good now?
![Page 71: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/71.jpg)
Thread-Safety ExampleThread-Safety Example
@ThreadSafepublic class CachedFactorizer implements Servlet { @GuardedBy("this") private BigInteger lastNumber, lastFactors[]; @GuardedBy("this") private long hits, cacheHits; public synchronized long getHits() { return hits; } public synchronized double getCacheHitRatio() { return (double) cacheHits / (double) hits; } public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = null; synchronized (this) { ++hits; if (i.equals(lastNumber)) { ++cacheHits; factors = lastFactors.clone(); } } if (factors == null) { factors = factor(i); synchronized (this) { lastNumber = i; lastFactors = factors.clone(); } } encodeIntoResponse(resp, factors); }}
Yes. The compound ac-tions are appropriately guarded in such a way
that still allows for con-currency.
![Page 72: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/72.jpg)
Thread-Safety ExampleThread-Safety Example
@ThreadSafepublic class CachedFactorizer implements Servlet { @GuardedBy("this") private BigInteger lastNumber, lastFactors[]; @GuardedBy("this") private long hits, cacheHits; public synchronized long getHits() { return hits; } public synchronized double getCacheHitRatio() { return (double) cacheHits / (double) hits; } public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = null; synchronized (this) { ++hits; if (i.equals(lastNumber)) { ++cacheHits; factors = lastFactors.clone(); } } if (factors == null) { factors = factor(i); synchronized (this) { lastNumber = i; lastFactors = factors.clone(); } } encodeIntoResponse(resp, factors); }}
Why do we no longer use AtomicLong vari-
ables?
![Page 73: Lecture 16: Thread Safety in Java - Department of … › comp › 150CCP › lectures › Lecture16.pdfLecture 16: Thread Safety in Java Dr. Richard S. Hall rickhall@cs.tufts.edu](https://reader034.vdocuments.us/reader034/viewer/2022042410/5f284a5acc9f4363975d8073/html5/thumbnails/73.jpg)
Thread-Safety ExampleThread-Safety Example
@ThreadSafepublic class CachedFactorizer implements Servlet { @GuardedBy("this") private BigInteger lastNumber, lastFactors[]; @GuardedBy("this") private long hits, cacheHits; public synchronized long getHits() { return hits; } public synchronized double getCacheHitRatio() { return (double) cacheHits / (double) hits; } public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = null; synchronized (this) { ++hits; if (i.equals(lastNumber)) { ++cacheHits; factors = lastFactors.clone(); } } if (factors == null) { factors = factor(i); synchronized (this) { lastNumber = i; lastFactors = factors.clone(); } } encodeIntoResponse(resp, factors); }}
Not necessary since ac-cess is already guarded.