240 likes | 378 Views
Inter-Thread communication State dependency: Guarded Methods. Monitors. Through synchronization one thread can safely change values that another thread will read; how does the second thread know that the values have changed?
E N D
Inter-Thread communicationState dependency: Guarded Methods Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Monitors • Through synchronization one thread can safely change values that another thread will read; how does the second thread know that the values have changed? • Check-and-act methods are methods designed to refuse to perform actions unless they can ensure actions will succeed, in part by checking their pre-conditions Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Policies on failed pre-conditions • Balking: throw an exception indicating refusal, not failure. • Guarded suspension: suspend action until the pre-condition becomes true • Time-outs: place a bound on the suspension. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Monitor mechanics • Guarded methods are usually built using the following methods: • Object.wait() • Object.notify() • Object.notifyAll() Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Strategies • For each condition that needs to be waited on, write a guarded wait loop that causes the current thread to block if guard is false. • Ensure that every method causing state changes that affect the truth value of any waited-for condition notifies threads waiting for state changes, causing them to wake up and recheck their guard conditions • A member variable is checked by waiting thread, and modified by thread doing the modification. The checking and modification occur inside synchronized methods to avoid race conditions. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Every object has a wait set manipulated by wait, notify, notifyAll, thread.interrupt() • Objects containing locks and wait sets are called monitors • Any Object (read class) can serve as a monitor • Because of the relationship between wait sets and locks, the methods wait, notify, notifyAll may be invoked only when the synchronization lock is held on their targets, a run-time error will be thrown otherwise Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
wait() • A wait invocation results in the following actions: • If current thread has been interrupted, method exists immediately throwing InterruptedException; otherwise the current thread is blocked. • JVM places the thread in the internal and inaccessible wait set associated with the target object. • Synchronization lock for target object is released, but all other locks held by thread are retained. • Full release is obtained even if lock is re-entrantly held due to nested synchronized calls on target object. Upon resumption the lock status is fully restored. • When wait pauses the thread, it atomically releases the lock on the object. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
notify(), notifyAll() • An arbitrary chose thread T, if exists is removed by the JVM from the internal wait set associated with target object. No guarantee on the threat T selected. • T must re-obtain the synchronization lock for the target object, which will always cause it to block at least until the thread calling notify releases the lock. It will continue to block if some other thread obtains lock first. • T is resumed from the point of its wait. • NotifyAll works essentially the same as notify, except that the steps occur, in effect simultaneously, for all threads in the wait set of the target object. However because they must acquire the lock, threads continue one at a time. • Fundamental difference between notify() and notifyAll() is that if more than one thread is waiting notification, notify() will only signal one of waiting threads, while notifyAll() signals all waiting threads. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Notify as an optimization • Using notify is an optimization over notifyAll when • All threads are waiting for same condition • At most one thread can benefit for the condition being met. • This is contractually true for all subclasses. • Otherwise use notifyAll. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Missed notification • Thread B signals threadA, but threadA is not yet waiting on the notification. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Early notification • If a thread is notified wile waiting, but the condition the thread is waiting for has not been met, thread received an early notification. • An early notification also occurs if condition is briefly met but quickly changes so is no longer met. This is due to subtle error in code: use a while for waiting not an if. • An example: two threads are waiting for an element to be added, and only one item is added. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Canceling a thread • There are occasions to cancel a running thread (user presses cancel button) • Cancellation is requested by interrupting the thread and writing the thread such that it watches for and responds to being interrupted Thread 1 thread 2 thread2.interrupt(); while(!interrupted())doSomeWork(); • An interrupt does not force the thread to halt, but it will interrupt sleeping or waiting threads. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Interrupts • If thread.interrupt() is invoked for a thread suspended in a wait, same notify mechanism applies, except that after re-acquiring the lock, wait method throws an InterruptedException and thread’s interrupt status is set to false. • NO telling behavior if an interrupt and a notify happen simultaneously. • isInterrupted() tests whether a thread has been interrupted. • interrupted(), a static method that tests whether the current thread has been interrupted, and then clears the “interrupted” state of the thread. It returns true if the thread had been interrupted; false otherwise. • Interrupted state of a thread can only be clear by that thread. There is no way for one thread to “un-interrupt” another thread. • One of the actions of an interrupted thread is to clean up before responding to the interrupt. • Methods sleep(), and wait() will throw InterruptedException; this exception will clear the interrupted state when thrown. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Blocking and interrupt() • Any method performing a blocking operation should be designed to be cancelled with interrupt() and should throw an appropriate exception if that occurs. • Example: sleep(), and wait() • In some systems, blocking I/O will respond to interruption by throwing InterruptedException • Even if the interruption cannot be responded to during I/O, systems may check for interruption at start of operation and throw the exception • Hence the need for an interrupted thread to clear its interrupted state if needs to perform I/O as part of its cleanup. • You cannot assume that interrupt() will unblock a thread that is performing I/O. • Golden rule: never hide an interrupt by clearing explicitely or by catching an InterruptedException and continuing normally. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Threads and object state • A thread dies when • The run method returns normally. • The run method completes abruptly. • The destroy method is invoked on the thread. • When a thread dies the thread object does not go away, so you can still access its state. • Useful when using the join() method. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Time waits: wait(long msecs), wait(long msecs, int nanosecs) • Operate as the untimed version, except that when time out occurs, it is released automatically without need for notification. • No status indication differentiating waits that return via notifications versus a time-out. • Counterintuitively, wait(0), and wait(0,0) are equivalent to wait() • A timed wait may resume an arbitrarily amout of time after the requested bound due to thread contention, scheduling policies, and timer granularities. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Class X { public synchronized void w() throws InterruptedException{ before(); wait(); after(); } public synchronized void n(){ notifyAll();} public void before(); public void after(); } T1T2 T3 x wait set begin x.w() acquire lock before(); wait: release lock enter wait set begin x.w() acquire lock before(); wait: release lock enter wait set begin x.n() Wait for lock acquire lock notifyAll() release lock T1 T2 Exit wait set Wait for lock Acquire lock After(); Release lock Exit wait set Wait for lock Acquire lock After(); Release lock Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Class X { public synchronized void w() throws InterruptedException{ before(); wait(); after(); } public synchronized void n(){ notifyAll();} public void before(); public void after(); } T1T2 T3 x wait set begin x.w() acquire lock before(); wait: release lock enter wait set begin x.w() acquire lock before(); wait: release lock enter wait set begin x.n() Wait for lock acquire lock notifyAll() release lock T1 T2 Exit wait set Wait for lock Acquire lock After(); Release lock Exit wait set Wait for lock Acquire lock After(); Release lock Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Cubby Hole example • And Queue example (ch8, ch18) Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
join API void join() Waits for this thread to die. void join(long millis) Waits at most millis milliseconds for this thread to die. void join(long millis, int nanos) Waits at most millis milliseconds plus nanos nanoseconds for this thread to die. • In general, join is a rather crude method for thread synchronization, but is need is wanted in some instances. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Ending application execution • Your application has at least one thread (the main()) created when application is invoked. All other threads are created by the main() thread or threads created by main. • Two kinds of threads: user and daemon. • An application terminates when all user threads terminate. • All daemon threads are destroyed by JVM when it detects that all user threads are finished. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Thread management and security: Thread group • Threads are organized into groups for management or security • Thread groups form a hierarchy starting with its top group or system thread group. • A thread group can be managed as a unit: • Interrupting all threads in a group at once. • Placing a limit on max priority of threads in group. • Used to define a security domain. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
Threads and exception • An uncaught exception in a thread will be handled • By the thread’s parent group if there is one. • By invoking the exception’s printStackTrace method is there is no parent group, so that information about the exception is displayed. • But recall, this print appears in a terminal screen. If app does not have a terminal screen the error will go unnoticed.!!!!! Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads
ThreadLocal • This class provides ThreadLocal variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal objects are typically private static variables in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID). • Each thread holds an implicit reference to its copy of a ThreadLocal as long as the thread is alive and the ThreadLocal object is accessible; after a thread goes away, all of its copies of ThreadLocal variables are subject to garbage collection (unless other references to these copies exist). Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads