I'm just trying to further my understanding of this concept.
We have a monitor, let's say a queue or a map of some sort. This monitor has methods to put objects on, and get objects off. In order to be thread safe, the monitor will lock on it's put methods and on it's get methods. When a thread is synchronized to this monitor, it's constantly trying to obtain this monitor's right's so it can proceed with what it needs to do. Does this sound right?
Another question, how does the flow of control work here. Which code is executed once the thread has gained access to the monitor? I'm finding it hard to debug multi-threaded programs with just print statements, it get's really messy and confusing.
public void run(){
try{
synchronized (monitor){
while (monitor is empty){
monitor.wait(); // Does this line pause the thread or the monitor?
}
System.out.println("Done Waiting");
}
System.out.println("Out of the synchronized block");
}
}
Here's the definition from the Java Language Specification:
The Java programming language provides multiple mechanisms for
communicating between threads. The most basic of these methods is
synchronization, which is implemented using monitors. Each object in
Java is associated with a monitor, which a thread can lock or unlock.
Only one thread at a time may hold a lock on a monitor. Any other
threads attempting to lock that monitor are blocked until they can
obtain a lock on that monitor. A thread t may lock a particular
monitor multiple times; each unlock reverses the effect of one lock
operation.
To answer
This monitor has methods to put objects on, and get objects off. In
order to be thread safe, the monitor will lock on it's put methods and
on it's get methods. When a thread is synchronized to this monitor,
it's constantly trying to obtain this monitor's right's so it can
proceed with what it needs to do. Does this sound right?
So you're not interacting with a monitor. A monitor doesn't have a concept of methods. Don't think of it like that. You interact with objects which have monitors. When a thread acquires an object's monitor, it doesn't need to constantly trying to obtain it, it already has it.
Another question, how does the flow of control work here. Which code
is executed once the thread has gained access to the monitor? I'm
finding it hard to debug multi-threaded programs with just print
statements, it get's really messy and confusing.
If execution enters the synchronized block on an object, the currently executing thread has acquired the monitor on the synchronized object, in this case the object referenced by the variable monitor.
I'll assume (thanks to Radiodeaf) that by monitor is empty, you mean your Map object doesn't have any entries.
When you call
monitor.wait();
the current thread releases the monitor on the object referenced by monitor and sleeps until it gets notified.
The javadoc of Object#wait() has more details.
So you will loop on the check for empty and wait if it returns true. We can assume that some other piece of code calls notify() when they put something into the Map.
When the object does get notified, the thread then has to compete to re-acquire the object's monitor. This is obviously necessary so that the thread can be executing inside a synchronized block on the object.
As we know We can call wait method only from synchronized context.
So By saying wait release the lock we mean that once lock is acquired on an object when it is in synchronized context , by calling wait method on same object , it release the lock and allow other thread to work on that object.
Related
Let's say you have two threads, thread1 and thread2. If you call thread1.start() and thread2.start() at the same time and they both print out numbers between 1 and 5, they will both run at the same time and they will randomly print out the numbers in any order, if I am not mistaken. To prevent this, you use the .join() method to make sure that a certain thread gets executed first. If this is what the .join() method does, what is the Lock object used for?
Thread.join is used to wait for another thread to finish. The join method uses the implicit lock on the Thread object and calls wait on it. When the thread being waited for finishes it notifies the waiting thread so it can stop waiting.
Java has different ways to use locks to protect access to data. There is implicit locking that uses a lock built into every Java object (this is where the synchronized keyword comes in), and then there are explicit Lock objects. Both of them protect data from concurrent access, the difference is the explicit Locks are more flexible and powerful, while implicit locking is designed to be easier to use.
With implicit locks, for instance, I can't not release the lock at the end of a synchronized method or block, the JVM makes sure that the lock gets released as the thread leaves. But programming with implicit locks can be limiting. For instance, there aren't separate condition objects so if there are different threads accessing a shared object for different things, notifying only a subset of them is not possible.
With explicit Locks you get separate condition objects and can notify only those threads waiting on a particular condition (producers might wait on one condition while consumers wait on another, see the ArrayBlockingQueue class for an example), and you can implement more involved kinds of patterns, like hand-over-hand locking. But you need to be much more careful, because the extra features introduce complications, and releasing the lock is up to you.
Locking typically prevents more than one thread from running a block of code at the same time. This is because only ONE thread at a time can acquire the lock and run the code within. If a thread wants the lock but it is already taken, then that thread goes into a wait state until the lock is released. If you have many threads waiting for the lock to be released, which one gets the lock next is INDETERMINATE (can't be predicted). This can lead to "thread starvation" where a thread is waiting for the lock, but it just never gets it because other threads always seem to get it instead. This is a very generic answer because you didn't specify a language. Some languages may differ slightly in that they might have a determinate method of deciding who gets the lock next.
Below is how monitor works:
monitor
Threads in wait set are waken up when Object.notifyAll() is called.
Only one of them get the lock, while the others are blocked again.
So where do the blocked threads go?Will they go back to wait set or go to entry set?Or this is managed by the os, because monitor depends on the os MutexLock?
The monitor is a fundamental conception that you should understand. It is better to read about it somewhere.
In short, I could say that there are some major principles:
If a thread go into the synchronized block - the monitor of synchronized object is blocked and all other threads couldn't
execute the synchronized block (they are in the Entry Set).
If you call wait() method on synchronized object, then the thread go to Wait Set
If you call notify()/notifyAll() method on synchronized object, it means that one/all thread(s) go to Entry Set from Wait Set.
The answer to your question is - when you call notifyAll() method, all threads from Wait Set go to Entry Set.
I was wondering if in Java I would get any odd behaviour if I synchronise twice on the same object?
The scenario is as follows
pulbic class SillyClassName {
object moo;
...
public void method1(){
synchronized(moo)
{
....
method2();
....
}
}
public void method2(){
synchronized(moo)
{
doStuff();
}
}
}
Both methods use the object and are synchronised on it. Will the second method when called by the first method stop because it's locked?
I don't think so because it's the same thread but I'm unsure of any other odd results that might occur.
Reentrant
Synchronized blocks use reentrant locks, which means if the thread already holds the lock, it can re-aquire it without problems. Therefore your code will work as you expect.
See the bottom of the Java Tutorial page Intrinsic Locks and Synchronization.
To quote as of 2015-01…
Reentrant Synchronization
Recall that a thread cannot acquire a lock owned by another thread. But a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block.
I think we have to use reentrant lock for what you are trying to do. Here's a snippet from http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html.
What do we mean by a reentrant lock? Simply that there is an acquisition count associated with the lock, and if a thread that holds the lock acquires it again, the acquisition count is incremented and the lock then needs to be released twice to truly release the lock. This parallels the semantics of synchronized; if a thread enters a synchronized block protected by a monitor that the thread already owns, the thread will be allowed to proceed, and the lock will not be released when the thread exits the second (or subsequent) synchronized block, but only will be released when it exits the first synchronized block it entered protected by that monitor.
Though I have not tried it, I guess if you want to do what you have above, you have to use a re-entrant lock.
Java appears to fully support nested locks on one object by the same thread. This means that if a thread has an outer and an inner lock on an object, and another thread tries to lock on the same object, the second thread will be suspended until both locks have been released by the first thread.
My testing was done under Java 6 SE.
No problems. In your example, (once you fix your code to get rid of the compile warnings that you'll get ;) ), the synchronization ensures that the blocks in method1 and method2 will not execute simultaneously.
That's kind of the point of synchronization. :)
Edit: Sorry, missed parts of your question, but Phill answered it. To summarize, a single thread cannot deadlock itself.
In java, the synchronized keyword on a method basically synchronizes on the current object, so in effect it's doing what you suggest above implicitly.
You won't experience problems with synchronizing on one object in one method and then synchronizing on the same object in another method because, as you say, the current thread already holds the lock on that object.
No, the second method will not stop if called by the first. No odd results will occur (Except a slight overhead for checking the lock. This won't matter much. From Java 6 onwards, you have lock coarsening in the JVM - Java SE 6 Performance White Paper.)
For example, take a look at source code of java.util.Vector. There are a lot of calls to other synchronized methods from within synchronized methods.
I have hard time to really understand, how that works:
while(<some condition>){
wait();
}
OR this example:
while(<some condition>){
condition.await();
}
When thread already passed the <some condition>,
it may really happen, that <some condition> already false when wait() or await() executed.
So wait() or await() may be called with already invalidated condition - that means the intention is broken.
What is wrong with my logic?
From the docs for wait():
The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
(emphasis mine)
In other words, without a synchronized block, your code will throw an IllegalMonitorStateException. With synchronized, on the other hand, your condition will be checked atomically with the wait(); call.
This does not automatically mean you have no problems, because "atomically" here is only with regard to the object you're synchronizing on (in your case this), and only relative to other synchronized access to that object. If your condition depends on different objects, or you access the object without synchronization somewhere else, things might go bad. Thus, don't do that.
The same reasoning goes for the use of Locks and Conditions. See this code sample. Condition variables are derived from lock objects, and synchronized/wait/notify is analogous to lock;unlock/await/signal.
Waking up from Object#wait() or Condition#await() means reacquiring the associated lock. Presumably, <some condition> should only be modified when owning the lock. So if the thread that woke up now owns the lock, no other thread should be able to change the condition to false.
Someone at work just asked for the reasoning behind having to wrap a wait inside a synchronized.
Honestly I can't see the reasoning. I understand what the javadocs say--that the thread needs to be the owner of the object's monitor, but why? What problems does it prevent? (And if it's actually necessary, why can't the wait method get the monitor itself?)
I'm looking for a fairly in-depth why or maybe a reference to an article. I couldn't find one in a quick google.
Oh, also, how does thread.sleep compare?
edit: Great set of answers--I really wish I could select more than one because they all helped me understand what was going on.
Lots of good answers here already. But just want to mention here that the other MUST DO when using wait() is to do it in a loop dependent on the condition you are waiting for in case you are seeing spurious wakeups, which in my experience do happen.
To wait for some other thread to change a condition to true and notify:
synchronized(o) {
while(! checkCondition()) {
o.wait();
}
}
Of course, these days, I'd recommend just using the new Condition object as it is clearer and has more features (like allowing multiple conditions per lock, being able to check wait queue length, more flexible schedule/interrupt, etc).
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
lock.lock();
try {
while (! checkCondition()) {
condition.await();
}
} finally {
lock.unlock();
}
}
If the object does not own the object monitor when it calls Object.wait(), it will not be able to access the object to setup a notify listener until the the monitor is released. Instead, it will be treated as a thread attempting to access a method on a synchronized object.
Or to put it another way, there is no difference between:
public void doStuffOnThisObject()
and the following method:
public void wait()
Both methods will be blocked until the object monitor is released. This is a feature in Java to prevent the state of an object from being updated by more than one thread. It simply has unintended consequences on the wait() method.
Presumably, the wait() method is not synchronized because that could create situations where the Thread has multiple locks on the object. (See Java Language Specifications/Locking for more info on this.) Multiple locks are a problem because the wait() method will only undo one lock. If the method were synchronized, it would guarantee that only the method's lock would be undone while still leaving a potential outer lock undone. This would create a deadlock condition in the code.
To answer your question on Thread.sleep(), Thread.sleep() does not guarantee that whatever condition you are waiting on has been met. Using Object.wait() and Object.notify() allows a programmer to manually implement blocking. The threads will unblock once a notify is sent that a condition has been met. e.g. A read from disk has finished and data can be processed by the thread. Thread.sleep() would require the programmer to poll if the condition has been met, then fall back to sleep if it has not.
It needs to own the monitor, since the purpose of the wait() is to release the monitor and let other threads obtain the monitor to do processing of their own. The purpose of these methods (wait/notify) is to coordinate access to synchronized code blocks between two threads that require each other to perform some functionality. It is not simply a matter of making sure access to a data structure is threadsafe, but to coordinate events between multiple threads.
A classic example would be a producer/consumer case where one thread pushes data to a queue, and another thread consumes the data. The consuming thread would always require the monitor to access the queue, but would release the monitor once the queue is empty. The producer thread would then only get access to write to the thread when the consumer is no longer processing. It would notify the consumer thread once it has pushed more data into the queue, so it can regain the monitor and access the queue again.
Wait gives up the monitor, so you must have it to give it up. Notify must have the monitor as well.
The main reason why you want to do this is to ensure that you have the monitor when you come back from wait() -- typically, you are using the wait/notify protocol to protect some shared resource and you want it to be safe to touch it when wait returns. The same with notify -- usually you are changing something and then calling notify() -- you want to have the monitor, make changes, and call notify().
If you made a function like this:
public void synchWait() {
syncronized { wait(); }
}
You would not have the monitor when wait returned -- you could get it, but you might not get it next.
Here's my understanding on why the restriction is actually a requirement. I'm basing this on a C++ monitor implementation I made a while back by combining a mutex and a condition variable.
In a mutex+condition_variable=monitor system, the wait call sets the condition variable into a wait state and releases the mutex. The condition variable is shared state, so it needs to be locked to avoid race conditions between threads that want to wait and threads that want to notify. Instead of introducing yet another mutex to lock its state, the existing mutex is used. In Java, the mutex is correctly locked when the about-to-wait thread owns the monitor.
Mostly wait is done if there is a condition say a queue is empty.
If(queue is empty)
queue.wait();
Let us assume the queue is empty.
In case if the current thread pre-empts after checking the queue, then if another
thread adds few elements to queue, the current thread will not know and will go for wait
state. Thats wrong.
So we should have something like
Synchornized(queue)
{
if(queue is empty)
queue.wait();
}
Now let us consider what if they made wait itself as synchronized. As already mentioned in one of the comments, it releases only one lock. That means if wait() was synchronized in the above code only one lock would have been released. Implies that current thread will go for wait with the lock for the queue.