How can I make a thread wait without releasing the lock ?
If this is not possible, then how can I pause a thread while a certain condition is not met and unpause it as soon the condition is met or when I notify it
Concept of wait/notify
Waiting/Notifying can only be done in the scope of a lock (e.g. a synchronized method or synchronized block).
Both the wait and notify should synchronize on the same object.
The waiting thread:
synchronized(lockObject) {
lockObject.wait(); <-- it will wait here until the notify is called.
}
The notifying thread:
synchronized(lockObject) {
lockObject.notify();
}
The lockObject can be anything. It could just be a new Object(), but very often it could be some collection, a logical object that represents a printer, ... anything.
Hint: Judging from the comments section, you may need the following: The notify releases just one waiting thread. But you could actually have multiple threads waiting. If you want to release all of them, use notifyAll.
Same thing, but with synchronized methods
Alternatively, you could create a class, and use method level locking.
class LockObject {
public synchronized void waitMethod() {
wait();
}
public synchronized void notifyMethod() {
notify();
}
}
Again both have to use the same object to lock on.
LockObject instance = new LockObject();
Then the waiting thread:
instance.waitMethod();
And the notifying thread:
instance.notifyMethod();
If you are serious about this
Also take a look inside the concurrency packages and tutorials of the JDK, and you will find more advanced locking objects. Just to name one, countdown latches are powerful.
Related
I am learning about cooperation between concurrent tasks and I have got that question and a possible answer to it. I would like to make sure I understand it correctly.
So to call a.wait() it is first required to synchronize on the object a or to be more precise a thread must become the owner of the a's monitor. As far as I understand, the only reason why a.wait() should be called in a synchronized context (together with a.notify()/a.notifyAll()) is to avoid a race condition/The Lost Wake-Up Problem. But theoretically, it is possible to avoid the race condition calling a.wait(),a.notify()/a.notifyAll() by synchronizing on some other object, like this:
Thread #1:
synchronized(b) {
…
a.wait(); // here a thread owns only one monitor: the monitor of the object stored in the variable b, where a != b
…
}
Thread #2:
synchronized(b) {
…
a.notify(); // the same here
…
}
The expected behavior is: the thread #1 acquires the monitor of b, enters the critical section, invokes a.wait(), then waits on a and releases the monitor of b. Afterwards the thread #2 acquires the monitor of b, enters the critical section, invokes a.notify() (the thread #1 gets notified), exits the critical section and releases the monitor of b, then the thread #1 acquires the monitor of b again and continues running. Thus, only one critical section synchronized on b can run at a time and no race condition can occur. You may ask, “but how would wait() know that the object b is used in this case to avoid the race condition and thus its monitor must be released?”. Well, that way it wouldn’t know. But maybe the wait method could take an object as an argument to know which object’s monitor to release, for example, a.wait(b), to wait on a and release the monitor of b. But there is no such an option: a.wait() causes a thread to wait on a and releases the monitor of exactly the same a. Period. The invocation of the wait and notify methods in the code above results in IllegalMonitorStateException.
According to this information from the Wikipedia article, the functionality of the wait, notify/notifyAll methods is built into every object's monitor where it is integrated into the functionality of the synchronization mechanism at the level of every individual object. But still it doesn't explain why it was done this way in the first place.
My answer to the question: before calling the wait method of an object, a thread should own the monitor of exactly the same object because to avoid a race condition this object is always not only a viable option but the best one.
Let’s see if there are any situations where it could be undesirable to synchronize on an object before invoking its wait, notify/notifyAll methods (plus some relevant logic). Synchronizing on the object would block it for other threads which could be undesirable if the object has some other synchronized methods (and/or there are some critical sections synchronized on the object) having nothing to do with the waiting logic. In that case it is always possible to refactor the corresponding class(es) so that the wait and notify/notifyAll methods operate on one object, while other synchronized methods/blocks operate on another one(s). For example, one of possible solutions could be creating a dedicated object specifically for a waiting logic (to wait and synchronize on) like in the example below:
public class A {
private Object lock = new Object(); // an object to synchronize and wait on for some waiting logic
private boolean isReady = false;
public void mOne() throws InterruptedException {
synchronized(lock) { // it blocks the instance of the Object class stored in the variable named lock
while(!isReady) {
lock.wait();
}
}
}
public void mTwo() {
synchronized(lock) { // the same here
isReady = true;
lock.notify();
}
}
synchronized public void mThree() { // it blocks an instance of A
// here is some logic having nothing to do with the above waiting and
// mThree() can run concurrently with mOne() and mTwo()
}
}
So there is no need to synchronize on some voluntary object to avoid a certain race condition regarding calling wait, notify/notifyAll methods. If it was allowed it would only cause unnecessary confusion.
Is it correct? Or maybe I am missing something here. I would like to make sure I don't miss anything important.
Oracle documentation: wait, notify, notifyAll
How can the wait() and notify() methods be called on Objects that are not Threads? That doesn't really make sense, does it?
Surely, it must make sense, however, because the two methods are available for all Java objects. Can someone provide an explanation? I am having trouble understanding how to communicate between threads using wait() and notify().
Locking is about protecting shared data.
The lock is on the data structure being protected. The threads are the things accessing the data structure. The locks are on the data structure object in order to keep the threads from accessing the data structure in an unsafe way.
Any object can be used as an intrinsic lock (meaning used in conjunction with synchronized). This way you can guard access to any object by adding the synchronized modifier to the methods that access the shared data.
The wait and notify methods are called on objects that are being used as locks. The lock is a shared communication point:
When a thread that has a lock calls notifyAll on it, the other threads waiting on that same lock get notified. When a thread that has a lock calls notify on it, one of the threads waiting on that same lock gets notified.
When a thread that has a lock calls wait on it, the thread releases the lock and goes dormant until either a) it receives a notification, or b) it just wakes up arbitrarily (the "spurious wakeup"); the waiting thread remains stuck in the call to wait until it wakes up due to one of these 2 reasons, then the thread has to re-acquire the lock before it can exit the wait method.
See the Oracle tutorial on guarded blocks, the Drop class is the shared data structure, threads using the Producer and Consumer runnables are accessing it. Locking on the Drop object controls how the threads access the Drop object's data.
Threads get used as locks in the JVM implementation, application developers are advised to avoid using threads as locks. For instance, the documentation for Thread.join says:
This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
Java 5 introduced explicit locks implementing java.util.concurrent.locks.Lock. These are more flexible than the implicit locks; there are methods analogous to wait and notify (await and signal), but they are on the Condition, not on the lock. Having multiple conditions makes it possible to target only those threads waiting for a particular type of notification.
You can use wait() and notify() to synchronize your logic. As an example
synchronized (lock) {
lock.wait(); // Will block until lock.notify() is called on another thread.
}
// Somewhere else...
...
synchronized (lock) {
lock.notify(); // Will wake up lock.wait()
}
with lock being the class member Object lock = new Object();
Think using a real life example, a washroom. When you want to use the washroom at your office, you have two options to make sure no one else will come to the washroom once you are using it.
Lock the washroom door, so everyone else will know that it's used by someone else when they try to open the door
Go to each person in the office, lock them to their chairs (or table, or whatever), go to washroom.
Which option would you take?
Yes, it's the same in the Javaland!.
So in the above story,
Washroom = Object you want to lock (that only you need to use)
Your staff colleagues = other threads that you want to keep out
So just like in real life, when you have some private business, you lock that object. And when you are done with that object, you let go of the lock!.
(Yes yes!, this is a very simple description on what happens. Of course the real concept is slightly different from this, but this is a starting point)
You can stop your thread for time as you want using static Thread class method sleep().
public class Main {
//some code here
//Thre thread will sleep for 5sec.
Thread.sleep(5000);
}
If you want to stop some objects you need to call this method's within syncronized blocks.
public class Main {
//some code
public void waitObject(Object object) throws InterruptedException {
synchronized(object) {
object.wait();
}
}
public void notifyObject(Object object) throws InterruptedException {
synchronized(object) {
object.notify();
}
}
}
P.S. I'm sory if I wrong understand your question (English is not my native)
When you put some code inside synchronized block:
sychronized(lock){...}
a thread wanting to perform whatever is inside this block first acquires a lock on an object and only one thread at a time can execute the code locked on the same object. Any object can be used as a lock but you should be careful to choose the object relevant to the scope. For example when you have multiple threads adding something to the account and they all have some code responsible for that inside a block like:
sychronized(this){...}
then no synchronization takes place because they all locked on different object. Instead you should use an account object as the lock.
Now consider that these threads have also method for withdrawing from an account. In this case a situation may occur where a thread wanting to withdraw something encounters an empty account. It should wait until there's some money and release the lock to other threads to avoid a deadlock. That's what wait and notify methods are for. In this example a thread that encounters an empty account releases the lock and waits for the signal from some thread that makes the deposit:
while(balance < amountToWithdraw){
lock.wait();
}
When other thread deposits some money, it signals other threads waiting on the same lock. (of course, code responsible for making deposits and withdrawals has to be synchronized on the same lock for this to work and to prevent data corruption).
balance += amountToDeposit;
lock.signallAll;
As you see the methods wait and notify only make sense inside synchronized blocks or methods.
In Java all Object implements these two methods, obviously if there are not a monitor those two methods are useless.
Actually, wait, notify member function should not belong to thread, the thing it should belong to name as condition variable which comes from posix thread . And you can have a look how cpp wrap this, it wrap it into a dedicated class std::condition_variable.
Java haven't do this kind encapsulation, instead, it wrap condition variable in more high level way: monitor (put the functionality into Object class directly).
If you don't know monitor or condition variable, well, that indeed make people confused at the beginning.
Wait and notify is not just normal methods or synchronization utility, more than that they are communication mechanism between two threads in Java. And Object class is correct place to make them available for every object if this mechanism is not available via any java keyword like synchronized. Remember synchronized and wait notify are two different area and don’t confuse that they are same or related. Synchronized is to provide mutual exclusion and ensuring thread safety of Java class like race condition while wait and notify are communication mechanism between two thread.
Locks are made available on per Object basis, which is another reason wait and notify is declared in Object class rather then Thread class.
In Java in order to enter critical section of code, Threads needs lock and they wait for lock, they don't know which threads holds lock instead they just know the lock is hold by some thread and they should wait for lock instead of knowing which thread is inside the synchronized block and asking them to release lock. this analogy fits with wait and notify being on object class rather than thread in Java.
Analogy : a Java thread is a user and the toilet is a block of code which the thread wishes to execute. Java provides a way to lock the code for a thread which is currently executing it using the synchorinized keywokd, and making other threads that wish to use it wait until the first thread is finished. These other threads are placed in the waiting state. Java is NOT AS FAIR as the service station because there is no queue for waiting threads. Any one of the waiting threads may get the monitor next, regardless of the order they asked for it. The only guarantee is that all threads will get to use the monitored code sooner or later.
Source
If you look at the following producer and consumer code:
sharedQueue Object acts inter-thread communication between producer and consumer threads.
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ProducerConsumerSolution {
public static void main(String args[]) {
Vector<Integer> sharedQueue = new Vector<Integer>();
int size = 4;
Thread prodThread = new Thread(new Producer(sharedQueue, size), "Producer");
Thread consThread = new Thread(new Consumer(sharedQueue, size), "Consumer");
prodThread.start();
consThread.start();
}
}
class Producer implements Runnable {
private final Vector<Integer> sharedQueue;
private final int SIZE;
public Producer(Vector<Integer> sharedQueue, int size) {
this.sharedQueue = sharedQueue;
this.SIZE = size;
}
#Override
public void run() {
for (int i = 0; i < 7; i++) {
System.out.println("Produced: " + i);
try {
produce(i);
} catch (InterruptedException ex) {
Logger.getLogger(Producer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private void produce(int i) throws InterruptedException {
// wait if queue is full
while (sharedQueue.size() == SIZE) {
synchronized (sharedQueue) {
System.out.println("Queue is full " + Thread.currentThread().getName() + " is waiting , size: "
+ sharedQueue.size());
sharedQueue.wait();
}
}
// producing element and notify consumers
synchronized (sharedQueue) {
sharedQueue.add(i);
sharedQueue.notifyAll();
}
}
}
class Consumer implements Runnable {
private final Vector<Integer> sharedQueue;
private final int SIZE;
public Consumer(Vector<Integer> sharedQueue, int size) {
this.sharedQueue = sharedQueue;
this.SIZE = size;
}
#Override
public void run() {
while (true) {
try {
System.out.println("Consumed: " + consume());
Thread.sleep(50);
} catch (InterruptedException ex) {
Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private int consume() throws InterruptedException {
//wait if queue is empty
while (sharedQueue.isEmpty()) {
synchronized (sharedQueue) {
System.out.println("Queue is empty " + Thread.currentThread().getName()
+ " is waiting , size: " + sharedQueue.size());
sharedQueue.wait();
}
}
//Otherwise consume element and notify waiting producer
synchronized (sharedQueue) {
sharedQueue.notifyAll();
return (Integer) sharedQueue.remove(0);
}
}
}
Source
"This method should only be called by a thread that is the owner of this object's monitor."
So I think you must make sure there is a thread who is the monitor on the object.
Object class is the correct place to make a lock available for every object.
Suppose there is a joint bank account and hence multiple users can use the same account for transactions through multiple channels. Currently, the account has a balance of 1500/- and the minimum amount balance to remain in the account is 1000/-. Now, the first user is trying to withdraw an amount of 500/- through ATM and another user is trying to purchase any goods worth 500/- through a swipe machine. Here whichever channel first access the account to perform the transaction acquires the lock on the account at first and the other channel will wait until the transaction is completed and the lock on the account is released as there is no way to know which channel has already acquired the lock and which channel is waiting to acquire a lock. Hence lock is always applied on the account itself rather than a channel. Here, we can treat the account as an object and the channel as a thread.
I'm very confusing about these two descriptions:
"The wait method blocks the calling thread and gives up the monitor lock"
"The notify method unblocks one waiting thread but does not give up the monitor lock"
Here is my questions:
I know each object in Java has a lock, but what is the "monitor lock" means? is it the same as the oject's lock?
Why notify method needs to give up the monitor lock?
If I try to make a object waiting with the following code:
class simpleTask extends Thread
{
int waitingTime;
public simpleTask(int waitingTime)
{
this.waitingTime = waitingTime;
}
public void run()
{
synchronized(this) // this is a reference of current object
{
try {
this.wait(waitingTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Like the first description above, is that means the the current object is blocked by synchronized keyword, and then wait method releases the lock?
I know each object in Java has a lock, but what is the "monitor lock" means? is it the same as the object's lock?
Yes, they are the same thing. They are also occasionally called the object's "mutex" and the object's "primitive lock". (But when someone talks about Lock, they are talking about this Java interface ... which is a different locking mechanism.)
Why notify method needs to give up the monitor lock?
The notify method doesn't give up the lock. It is your code's responsibility to give up the lock (i.e. leave the synchronized block or return from the synchronized method) after the notify call returns.
Why is that necessary? Because any other thread that is currently waiting on that lock (in a wait(...) call) has to reacquire that lock before the wait call can complete.
Why did they design notify / wait like this? So that they can be used to implement condition variables.
Like the first description above, is that means the the current object is blocked by synchronized keyword, and then wait method releases the lock?
That is correct. When a thread calls someObject.wait() its lock on someObject is released ... and then reacquired (by the same thread) before the wait() call returns. Of course, in the meantime the lock someObject may have been acquired and released multiple times by other threads. The point is that when wait returns, the thread that called wait will have the lock.
Yes, the monitor lock is the same as the object's lock. If you do synchronized (object), that's the lock.
In your example, the current object will give up the lock while waiting, the wait() call gives up the lock. In another thread, notify() is called to wake the object up, and when the wait() call returns it will hold the lock again.
A monitor is a type of synchronization construct.
The reason that waiting gives up the lock is so that other threads can acquire the lock, such as other threads that might want to wait. Also: It's usual for the thread that's awakening other threads to lock before releasing any threads, to prevent a race condition.
For more about this, you should study condition variables (i.e. condvars).
Thread 1:
if(!conditionFullfiled) this.wait();
Thread 2:
if(conditionFullfiled) thread1.notify();
I want to wake up thread 1 from thread 2, when some condition is fullfiled. But isn't there a problem, when thread1.notify() is called if(!conditionFullfiled) ***HERE*** this.wait(); ?
To do obj.wait() and obj.notify(), you need to own the monitor of the object you're going to wait/notify on. In your code, you probably don't want thread1.notify(). Example:
Object someSharedObject = ...
Thread1:
synchronized(someSharedObject) {
// while NOT if for spurious wake ups.
while(!conditionFullfiled) someSharedObject.wait();
}
Thread2:
synchronized(someSharedObject) {
if(conditionFullfiled) someSharedObject.notify(); // this wakes thread1
}
The synchronized lock is on someSharedObject (can be this), which means the two threads will never clash. .wait() releases the currently held monitor, so Thread2 will not be blocked when Thread1 is waiting.
Edit: I learnt something about spurious wake ups. The .wait() must be done in a while loop - if is not enough. Why do threads spontaneously awake from wait()? . Thanks Enno Shioji for teaching me.
Edit: Clarified .wait() releases monitor.
You have 2 problems here.
you should not call wait() and notify() on thread object itself. Better way to do this is to use special lock object, e.g.
private Object lock = new Object();
......
lock.wait();
The next problem is that you have to call both wait() and notify into synchornized block, i.e.
syncronized(lock) {
// some code
lock.wait();
}
then in other place in code say:
syncronized(lock) {
lock.notify(); // this line will cause the wait to terminate and the first thread to continue.
}
It is convenient to localize both wait() and notify() wrapping methods in one class, so they have access to lock object.
For more information read
http://download.oracle.com/javase/6/docs/api/
http://download.oracle.com/javase/6/docs/api/java/lang/Thread.html
No problem at all since wait releases object lock (in case this).
It's a best practice to guard wait/notify conditions in while blocks - to avoid spurious wake-ups.
What object you use as "this"? If you invoke wait() on thread1 object, and both statements you have shown are wrapped in a loop like this:
new Runnable() {
synchronized (thread1) {
thread1.wait()
}
}
Then your code will work as you want. (First thread will halt when condition is false, and work otherwise).
The trick is that interactions on the thread object are synchronized, so one thread can not interrupt while other is working with the object.
EDIT:
It will be even better if you will synchronize not on the thread, but on some other object (you can simply create pure object to provide locks).
I'm coming from .NET world, and unfortunately looking Java source with .NET's eyes.
Following code is from Android Apps (though not Android specific at all):
private class Worker implements Runnable {
private final Object mLock = new Object();
private Looper mLooper;
Worker(String name) {
Thread t = new Thread(null, this, name);
t.start();
synchronized (mLock) {
while (mLooper == null) {
try {
mLock.wait();
} catch (InterruptedException ex) {
}
}
}
}
public Looper getLooper() {
return mLooper;
}
public void run() {
synchronized (mLock) {
Looper.prepare();
mLooper = Looper.myLooper();
mLock.notifyAll();
}
Looper.loop();
}
public void quit() {
mLooper.quit();
}
}
I'm not precisely clear with how synchronized works.
First I thought that synchronized is locking mLock object, but then if after t.start() constructor thread enters sync block first, it would block it at mLock.wait(), and implicitly block thread "t" by blocking it from entering synchronized block.
This is obviously wrong, because my phone rings as supposed :)
Next thought is that synchronize synchronizes "code block" (in which case, there two synchronized block are independent => threads can enter two different sync block at same time without restriction), and that fitted perfectly...
... until my colleague told me that mLock.wait() releases lock on mLock and enables other thread to enter critical section on mLock in same time.
I'm not sure if I was clear enough, so will gladly answer any further questions on this.
Check out the javadoc on Object.wait(). It's "magic" in that it drops the monitor that was acquired when entering the synchronized {} block. That allows another thread to acquire the monitor and call Object.notify().
When another thread calls notify() to wake the waiting thread from its wait() call, the waiting thread must re-acquire the monitor and will block until it can -- the monitor is only dropped for the duration of the wait() call. And the notifying thread completes its synchronized block before the newly-awoken waiting thread can proceed. Everything is sequenced predictably.
synchronized uses object monitors. Calling wait() on the object atomically releases the object monitor (for otherwise no other thread could ever take the monitor and issue a notify to the waiter(s)).
Yes. If you read the description of the wait() method, you'll learn that it causes the thread to release the lock and block until another thread invokes notify or notifyAll on the lock. The current thread waits until it can re-acquire the lock, and once it does, it continues execution.
The code shown follows poor practice, however, because it "publishes" (that is, it makes the object accessible to other threads) the Worker instance before it is fully constructed. The use of additional barriers in this method, combined with the private nature of the class, probably make this case safe, but in general, it is not.
Let me explain:
The constructor launches a new thread that will execute the run() method.
This new thread will obtain a new Looper object, store it in the mLooper field and then run the Looper message loop. In between it will notify() the first thread that mLooper has been set.
The first thread will therefore return from the constructor only after mLooper has been set which means that processing of Looper.loop(), by the 2nd thread, is bound to start shortly/has already started.