+ All Categories
Home > Documents > More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other...

More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other...

Date post: 18-Aug-2020
Category:
Upload: others
View: 2 times
Download: 0 times
Share this document with a friend
80
More Threads Thread Safety and locks Oleg Šelajev @shelajev [email protected] October 18, 2016
Transcript
Page 1: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

More Threads Thread Safety and locks

Oleg Šelajev @shelajev

[email protected]

October 18, 2016

Page 2: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

2

● Homework is an individual assignment ● Copying work is forbidden ● Sharing work is frown upon

Page 3: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

3

Page 4: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Agenda● Executors & sharing variables ● Locks ● Idioms & circus ● Homework

2

Page 5: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Java Language Specification, Chapter 17:

http://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html

https://www.youtube.com/watch?v=TxqsKzxyySo

Java Memory Model Pragmatics

Page 6: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

• Java Memory Model Pragmatics (transcript) • https://shipilev.net/blog/2014/jmm-

pragmatics/

• Close Encounters of The Java Memory Model Kind

• https://shipilev.net/blog/2016/close-encounters-of-jmm-kind/

Page 7: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Task• Tasks are independent activities

Page 8: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread
Page 9: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Executing Tasks Sequentially class SingleThreadWebServer { public static void main(String[] args) { ServerSocket socket = new ServerSocket(80); while (true) { Socket connection = socket.accept(); handleRequest(connection); } } }

Page 10: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Explicitly Creating Threadsclass ThreadPerTaskWebServer { public static void main(String[] args) { ServerSocket socket = new ServerSocket(80); while (true) { final Socket connection = socket.accept(); Runnable task = new Runnable() { public void run() { handleRequest(connection); } }; new Thread(task).start(); } } }

Page 11: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Disadvantages of Unbounded Thread Creation

• Thread lifecycle overhead • Resource consumption • Stability

Page 12: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

THREAD POOLS

A thread pool pattern consists of a number m of threads,

created to perform a number n of tasks concurrently.

Page 13: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Executorinterface Executor { void execute(Runnable command);}

Page 14: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Web Server Using a Thread Poolclass TaskExecutionWebServer { public static void main(String[] args) { Executor exec = Executors.newFixedThreadPool(100); ServerSocket socket = new ServerSocket(80); while (true) { final Socket connection = socket.accept(); Runnable task = new Runnable() { public void run() { handleRequest(connection); } }; exec.execute(task); } } }

Page 15: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread
Page 16: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Advantages of Thread Pools• Minimal thread lifecycle overhead • Enable to have enough threads to keep the

processors busy • Limit the number of threads to avoid

OutOfMemoryError

Page 17: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Execution Policies• In what thread will tasks be executed? • In what order should tasks be executed (FIFO,

LIFO, priority order)? • How many tasks may execute concurrently? • How many tasks may be queued pending

execution?

Page 18: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Execution Policies (2)• If a task has to be rejected because the system is

overloaded, which task should be selected as the victim, and how should the application be notified?

• What actions should be taken before or after executing a task?

Page 19: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

NEW THREADPOOL()

int corePoolSize – the number of threads initially int maximumPoolSize – are we growing the pool? long keepAliveTime, TimeUnit unit – any spare threads? BlockingQueue queue - how to store tasks RejectedExecutionHandler handler - rejection strategy

Page 20: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Thread Pools• Executors.newFixedThreadPool(int nThreads) • Executors.newCachedThreadPool() • Executors.newSingleThreadExecutor() • Executors.newScheduledThreadPool()

Page 21: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

ScheduledThreadPoolExecutor• Enables to schedule tasks

• after a given delay • at the specified time

• Enables to repeat tasks • at fixed rate • at fixed delay

Page 22: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Executor Lifecycle States1. Running 2. Shutting down 3. Terminated

Page 23: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Executor Lifecycleinterface ExecutorService extends Executor { void shutdown() List<Runnable> shutdownNow() boolean isShutdown() boolean isTerminated() boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException … }

Page 24: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Task Lifecycle States1. Created 2. Submitted 3. Started 4. Completed

Each task can be also cancelled

Page 25: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Executing Batch of Tasksinterface ExecutorService extends Executor { <T> List<Future<T>> invokeAll( Collection<? extends Callable<T>> tasks) <T> T invokeAny( Collection<? extends Callable<T>> tasks) ...}

Page 26: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

CompletionServiceinterface CompletionService<V> { Future<V> submit(Callable<V> task); Future<V> submit(Runnable task, V result); Future<V> take() throws InterruptedException; Future<V> poll(); Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException;}

Page 27: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Result-bearing Tasksinterface ExecutorService extends Executor { <T> Future<T> submit(Callable<T> task) <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task); ...} interface Callable<V> { V call() }

Page 28: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Result-bearing Tasks (2)interface Future<V> { boolean cancel(boolean mayInterrupt) boolean isCancelled() boolean isDone() V get() V get(long timeout, TimeUnit unit)}

Page 29: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Lock Objects

Page 30: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Keeping a Lockclass KeepLock extends Thread { private final Object lock; public KeepLock(Object lock) { this.lock = lock; } public void run() { try { synchronized (lock) { while (true) Thread.sleep(1000); // doing stuff } } catch (InterruptedException e) { } }}

Page 31: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Keep a Lock for a Secondpublic class KeepLockClient { public void myMethod() throws Exception { Object lock = new Object(); Thread t = new KeepLock(lock); t.start(); Thread.sleep(1000); t.interrupt(); }}

Page 32: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Keep a Lock for a Second (2)public class KeepLockClient { public void myMethod() throws Exception { Object lock = new Object(); Thread t1 = new KeepLock(lock); Thread t2 = new KeepLock(lock); // -added- t1.start(); Thread.sleep(1000); t2.start(); // -added- t1.interrupt(); Thread.sleep(1000); // -added- t2.interrupt(); // -added- }}

Page 33: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Keep a Lock for a Second (3)public class KeepLockClient { public void myMethod() throws Exception { Object lock = new Object(); Thread t1 = new KeepLock(lock); Thread t2 = new KeepLock(lock); t1.setDaemon(true); // -added- t1.start(); Thread.sleep(1000); t2.start(); //t1.interrupt // -removed- t2.interrupt();

}}

Page 34: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Oops!

• We cannot interrupt the second thread while the first thread is not interrupted

• The second thread could be stuck forever!

Page 35: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Keeping a Lockclass KeepLock extends Thread { private final Object lock; public KeepLock(Object lock) { this.lock = lock; } public void run() { try { synchronized (lock) { while (true) Thread.sleep(1000); // doing stuff } } catch (InterruptedException e) { } }}

Page 36: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Lock Object vs Monitor• Locks are similar to synchronized methods and statements, but more flexible

• Customisable (custom conditions, non-sequential lock acquisition/release, deadlock detection, etc.)

Lock l = ...;l.lock();try { // access the resource protected by this lock} finally { l.unlock();}

Page 37: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Lock Interfacepublic interface Lock { void lock(); // acquire lock, wait void lockInterruptibly() throws InterruptedException; // acquire lock, wait, interruptible boolean tryLock(); // acquire lock, immediate boolean tryLock(long time, TimeUnit unit) throws InterruptedException; // acquire lock, immediate, timed, interruptible void unlock(); // release lock Condition newCondition(); //}

Page 38: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Memory Visibility of Locks• All Lock implementations must enforce the same memory synchronization

semantics as provided by the built-in monitor lock, as described in section 17.4 of The Java™ Language Specification:

- A successful lock operation has the same memory synchronization effects as a successful Lock action.

- A successful unlock operation has the same memory synchronization effects as a successful Unlock action.

• Unsuccessful locking and unlocking operations, and reentrant locking/unlocking operations, do not require any memory synchronization effects.

Page 39: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

ReentrantLock• A re-entrant mutual exclusion Lock with the same basic behavior

and semantics as the implicit monitor lock accessed using synchronized methods and statements, but with extended capabilities.

- Interruptible

- Timed

- Fairness

• Returns immediately if the lock is held by the current thread

Page 40: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Keep a Lock Interruptiblyclass KeepLock extends Thread { private final ReentrantLock lock; public KeepLock(ReentrantLock lock) { this.lock = lock; } public void run() { try { lock.lockInterruptibly(); try { while (true) Thread.sleep(1000); // doing stuff } finally { lock.unlock(); } } catch (InterruptedException e) {} }}

Page 41: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Keep a Lock for a Second (4)public class KeepLockClient { public void myMethod() throws Exception { ReentrantLock lock = new ReentrantLock(); // -updated- Thread t1 = new KeepLock(lock); Thread t2 = new KeepLock(lock); t1.setDaemon(true); t1.start(); Thread.sleep(1000); t2.start(); // t1.interrupt t2.interrupt(); }}

Page 42: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

ReadWriteLockA lock that offers better concurrent access. Useful for synchronisation when reads are frequent and writes infrequent

• Read lock can be held by multiple threads as long as write lock is not held.

• Write lock is exclusive

• Must guarantee that the memory synchronization effects of writeLock operations also hold with respect to the associated readLock. A thread successfully acquiring the read lock will see all updates made upon previous release of the write lock.

interface ReadWriteLock { Lock readLock(); Lock writeLock();}

Page 43: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

StampedLockWriting. Method writeLock() possibly blocks waiting for exclusive access, returning a stamp that can be used in method unlockWrite(long) to release the lock.

Reading. Method readLock() possibly blocks waiting for non-exclusive access, returning a stamp that can be used in method unlockRead(long) to release the lock.

Optimistic Reading. Method tryOptimisticRead() returns a non-zero stamp only if the lock is not currently held in write mode. Method validate(long) returns true if the lock has not been acquired in write mode since obtaining a given stamp.

Page 44: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

StampedLockclass Point { private double x, y; private final StampedLock sl = new StampedLock();

double distanceFromOrigin() { // A read-only method long stamp = sl.tryOptimisticRead(); double currentX = x, currentY = y; if (!sl.validate(stamp)) { // if we are unlucky stamp = sl.readLock(); // read properly try { currentX = x; currentY = y; } finally { sl.unlockRead(stamp); // unlock the read } } return Math.sqrt(currentX * currentX + currentY * currentY); }

Page 45: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Liveness Hazards

Page 46: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Deadlock• When a thread holds a lock forever, other threads attempting to acquire

that lock will block forever waiting.

• When thread A holds lock L and tries to acquire lock M, but at the same time thread B holds M and tries to acquire L, both threads will wait forever

• No way to resolve a deadlock on a JVM, when a set of threads deadlock, thats it. The only way to restore the application to health is to abort and restart it - and hope the same thing doesn’t happen again.

• Depending on what those threads do, the application may stall completely, or a particular subsystem may stall, or performance may suffer.

Page 47: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

LeftRightDeadlockclass LeftRightDeadlock { private final Object left = new Object(); private final Object right = new Object(); public void leftRight() { synchronized (left) { synchronized (right) { doSomething(); } } } public void rightLeft() { synchronized (right) { synchronized (left) { doSomethingElse(); } } }}

Page 48: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Lock-ordering Deadlocks• The deadlock in LeftRightDeadlock came about because the two

threads attempted to acquire the same locks in a different order.

• If they asked for the locks in the same order, there would be no cyclic locking dependency and therefore no deadlock.

• If you can guarantee that every thread that needs locks L and M at the same time always acquires L and M in the same order, there will be no deadlock

Page 49: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Dynamic Lock Ordering• Sometimes it is not obvious that you have sufficient control over

lock ordering to prevent deadlocks

public void transferMoney(Account fromAccount, Account toAccount, Amount amount) throws InsufficientFundsException { synchronized (fromAccount) { synchronized (toAccount) { if (fromAccount.getBalance().compareTo(amount) < 0) throw new InsufficientFundsException(); else { fromAccount.debit(amount); toAccount.credit(amount); } } }}

Page 50: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Avoiding Deadlocks• If possible, never acquire more than one lock

• When acquiring multiple locks, ensure that lock ordering is consistent across your entire program

- Using open calls to alien methods wherever possible simplifies this substantially

• Use Lock.tryLock(long time, TimeUnit unit)

Page 51: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Thread-dump Analysis• While preventing deadlocks is mostly your problem, the JVM can

help identify them when they do happen using thread dumps.

• A thread dump includes a stack trace for each running thread, similar to the stack trace that accompanies an exception.

• Thread dumps also include locking information, such as which locks are held by each thread, in which stack frame they were acquired, and which lock a blocked thread is waiting to acquire

Page 52: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Example Thread-dumpFound one Java-level deadlock: ============================="ApplicationServerThread ": waiting to lock monitor 0x080f0cdc (a MumbleDBConnection), which is held by "ApplicationServerThread" "ApplicationServerThread ": waiting to lock monitor 0x080f0ed4 (a MumbleDBCallableStatement), which is held by “ApplicationServerThread"

Java stack information for the threads listed above: "ApplicationServerThread ": at MumbleDBConnection.remove_statement - waiting to lock <0x650f7f30> (a MumbleDBConnection) at MumbleDBStatement.close - locked <0x6024ffb0> (a MumbleDBCallableStatement) ...

"ApplicationServerThread ": at MumbleDBCallableStatement.sendBatch - waiting to lock <0x6024ffb0> (a MumbleDBCallableStatement) at MumbleDBConnection.commit - locked <0x650f7f30> (a MumbleDBConnection) ...

Page 53: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Generating Thread-dumps

• Send the JVM process a SIGQUIT signal (kill -3) on Unix platforms

• Press the Ctrl-\ key on Unix platforms

• Press Ctrl-Break on Windows platforms

• Many IDEs can request a thread dump also

Page 54: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Other Liveness Hazards• Starvation - occurs when a thread is perpetually denied access to

resources it needs in order to make progress; the most commonly starved resource is CPU cycles. Can be caused by inappropriate use of thread priorities

• Poor responsiveness - CPU-intensive background tasks can affect responsiveness of GUI because they compete for CPU cycles with the event thread

• Livelock - A thread, while not blocked, still cannot make progress because it keeps retrying an operation that will always fail. Overeager error-recovery code that mistakenly treats an unrecoverable error as a recoverable one

Page 55: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

http://www.amazon.com/The-Multiprocessor-Programming-Revised-Reprint/dp/0123973376

The Art of Multiprocessor Programming

by Maurice Herlihy, Nir Shavit

Page 56: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Concurrent programs• “No set of operations performed sequentially or concurrently on

instances of a thread-safe class can cause an instance to be in an invalid state.”

• Manages access to shared mutable state

• Visibility across different threads of execution

• Atomicity of compound operations

Page 57: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Sharing Variablesclass TellMeTheNumber { static boolean ready; static int number; static class ReaderThread extends Thread { public void run() { while (!ready) Thread.yield(); System.out.println(number); } } public static void main(String[] args) { new ReaderThread().start(); number = 42; ready = true; }}

Page 58: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Visibility• Visibility in a single thread is natural and intuitive

• In multi-threaded applications, things that can go wrong are subtle and counterintuitive

• Visibility across threads must be ensured by using proper synchronisation

• Happens-before relationship

Page 59: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Locking and Visibility• Threads entering synchronized blocks guarded by the same lock

see the each other writes.

• Without synchronization, there is no such guarantee.

- You could see stale values

- Stale data can cause serious and confusing failures such as unexpected exceptions, corrupted data structures, inaccurate computations, and infinite loops.

Page 60: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

MutableIntegerpublic class MutableInteger { private int value; public int get() { return value; } public void set(int value) { this.value = value; }}

Page 61: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Volatile• The visibility effects of volatile variables extend beyond the value of

the volatile variable itself. When thread A writes to a volatile variable and subsequently thread B reads that same variable, the values of all variables that were visible to A prior to writing to the volatile variable become visible to B after reading the volatile variable.

• From a memory visibility perspective, writing a volatile variable is like exiting a synchronized block and reading a volatile variable is like entering a synchronized block

• Be careful of compound operations!!

Page 62: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

MutableInteger (volatile)public class MutableInteger { private volatile int value; public int get() { return value; } public void set(int value) { this.value = value; }}

Page 63: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

“Out-of-thin-air Safety”• “Out-of-thin-air” safety - When a thread reads a variable without

synchronization, it may see a stale value, but at least it sees a value that was actually placed there by some thread and not some random value

• The Java Memory Model requires fetch and store operations to be atomic, except…

• …The fetch and store operations for 64-bit numeric variables (double and long) that are not declared or otherwise synchronised, can be treated as two separate 32-bit operations

Page 64: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Reordering Operations

• Operations can be reordered by

- compiler

- processor

- runtime

Page 65: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Atomicity• Compound operations that from a perspective of another thread

should be atomic - either all operations are done or none of them

- check-then-act (lazy initialization)

- read-modify-write (increment operation)

• Use classes in the java.util.concurrent.atomic package or proper synchronization to ensure atomicity

Page 66: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Check-then-actpublic Object remove(Object key) { Object value = map.get(key); if (value == null) { value = calculateValue(key); map.put(key, value); } return value;}

Page 67: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Sharing Objects

Page 68: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Publishing an Object• Naive way of publishing an object

• Publishes the internal representation, allows clients to both directly modify the set as well as the secrets therein

public static Set<Secret> knownSecrets;

public void initialize() { knownSecrets = new HashSet<Secret>();}

Page 69: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Publishing an Object• In many situations, we want to ensure that objects and their

internals are not published.

• In other situations, we do want to publish an object for general use, but doing so in a thread-safe manner may require synchronization

• Publishing internal state variables can compromise encapsulation and make it more difficult to preserve invariants

• Publishing objects before they are fully constructed can compromise thread safety.

Page 70: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Escaping Internal Mutable State• Not much better, client code can modify the states array.

• States array has escaped, was meant to be privateclass UnsafeStates { private String[] states = new String[]{“AK",“AL",…};

public String[] getStates() { return states; }}

Page 71: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Publication and Escape• Publishing an object means making it available to code outside of its

current scope, such as by storing a reference to it where other code can find it, returning it from a non-private method, or passing it to a method in another class

• Object internals should generally not be published

• Publishing an object for general use should be done in a thread-safe manner

• An object that is published when it should not have been is said to have escaped

Page 72: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Safe Construction• An object is in a predictable, consistent state only after its constructor returns, so

publishing an object from within its constructor can publish an incompletely constructed object

- Do not let the this reference to escape

- Creating an instance of an anonymous inner class includes a reference to this. avoid passing it to a method of a constructor argument

- For example: creating an instance of a Runnable and starting a Thread in a constructor

- Consider creating a static factory method to start the thread after construction

Page 73: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Unsafe Constructionpublic class ThisEscape { public ThisEscape(EventSource source) { source.registerListener(new EventListener() { public void onEvent(Event e) { doSomething(e); } }); … }}

Page 74: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Thread Confinement• One way to avoid accessing shared data is to not share

• If data is only accessed from a single thread, no synchronization is needed.

- JDBC Connection pools

• Thread confinement is an element of your program’s design that must be enforced by its implementation. The language has no mechanism for confining an object to a thread.

Page 75: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

ThreadLocal

• ThreadLocal provides get and set accessor methods that maintain a separate copy of the value for each thread that uses it

• A get returns the most recent value passed to set from the currently executing thread

Page 76: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

ThreadLocal Exampleprivate static ThreadLocal<String> myThreadLocal = new ThreadLocal<String>() { public String initialValue() { return "initialValue"; }}; public void myMethod() { myThreadLocal.get(); myThreadLocal.set("newValue");}

Page 77: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Homework #8

Page 78: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Homework #8Write a Java program which demonstrates concurrent transfers of money.

1. Create n number of accounts with each having n as its initial balance. Take n from the program’s main arguments.

2. Implement a method for transferring a given amount from one account to another.

3. Implement a method for printing balances of all accounts as well as their sum. Output form (single line): b1 b2 b3 ... bn sum

4. For each (source) account create a donator thread with a list of recipients - a shuffled list of all accounts except the source one.

Page 79: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Homework #85. A donator thread must transfer 1 unit from source account to each recipient account

sleeping 100ms after each transfer. After those transfers, the thread must stop

6. Print all balances before starting the transfers, after the transfers have finished and during the transfers once per 100ms.

7. Transfers must be thread safe and run concurrently if they have no accounts in common – lock on the source and target accounts but avoid deadlocks.

8. Printing all balances must be thread safe. The sum of all accounts must stay consistent. Stop all transfers while printing the balances - use ReadWriteLock.readLock() around printing the balances and a ReadWriteLock.writeLock() around each transfer

Page 80: More Threads Thread Safety and locks · Deadlock • When a thread holds a lock forever, other threads attempting to acquire that lock will block forever waiting. • When thread

Homework #89. Create all donator threads before actually starting them

10.Buffer program’s output: PrintStream out = new PrintStream(new BufferedOutputStream(System.out));

11.After all donator threads are finished, print all balances and flush the program’s output

12.Don’t use exit() or halt() to stop the program


Recommended