Static methods synchronize on the
class lock. Acquiring and relinquishing a class lock by a thread in order to
execute a static synchronized method is analogous to that of an object lock for
a synchronized instance method.
A thread acquires the class lock before it can
proceed with the execution of any static synchronized method in the class,
blocking other threads wishing to execute any static synchronized methods in
the same class.
This does not apply to static, non-synchronized methods, which
can be invoked at any time.
A thread acquiring the lock of a class to execute a
static synchronized method has no effect on any thread acquiring the lock on
any object of the class to execute a synchronized instance method.
In other
words, synchronization of static methods in a class is independent from the
synchronization of instance methods on objects of the class. A subclass decides
whether the new definition of an inherited synchronized method will remain synchronized
in the subclass.
Waiting
and Notifying
Waiting
and notifying provide means of communication between threads that synchronize
on the same object . The threads execute wait() and notify()
(or notifyAll()) methods on the shared object for this purpose.
These final methods
are defined in the Object class and, therefore, inherited by all objects. These
methods can only be executed on an object whose lock the thread holds (in other
words, in synchronized code), otherwise, the call will result in an IllegalMonitorStateException.
final
void wait(long timeout) throws InterruptedException
final
void wait(long timeout, int nanos) throws InterruptedException
final
void wait() throws InterruptedException
A
thread invokes the wait() method on the object whose lock it holds. The thread
is added to the wait set of the current object.
final
void notify()
final
void notifyAll()
A
thread invokes a notification method on the current object whose lock it
holds to notify thread(s) that
are in the wait set of the object.
Communication
between threads is facilitated by waiting and notifying, as illustrated
by
Figure below.
A
thread usually calls the wait() method on the object whose lock it holds
because a condition for its continued execution was not met.
The
thread leaves the Running state and transits to the Waiting-for notification state.
There
it
waits for this condition to occur. The thread relinquishes ownership of the
object lock.
Transition
to the Waiting-for-notification state and relinquishing the object lock are
completed as one atomic (non-interruptible) operation. The releasing of the
lock of the shared object by the thread allows other threads to run and execute
synchronized code on the same object after acquiring its lock. Note that the
waiting thread relinquishes only the lock of the object on which the
wait()
method was invoked. It does not relinquish any other object locks that it might
hold, which will remain locked while the thread is waiting. Each object has a
wait set containing threads waiting for notification. Threads in the Waiting-for-notification
state are grouped according to the object whose wait() method they invoked.
Figure
above shows a thread t that first acquires a lock on the shared object, and afterward
invokes the wait() method on the shared object. This relinquishes the object
lock and the thread t awaits to be notified. While the thread t is waiting, another
thread t can acquire the lock on the shared object for its own purposes. A
thread in the Waiting-for-notification state can be awakened by the occurrence of
any one of these three incidents:
1.
Another thread invokes the notify() method on the object of the waiting
thread,
and the waiting thread is selected as the thread to be awakened.
2.
The waiting thread times out.
3.
Another thread interrupts the waiting thread.
notify()
does not release lock, but when block will complete lock will be released by thread.
No comments:
Post a Comment