Java synchronized method documentation seems wrong - java

The Oracle lesson on concurrency in Java states:
it is not possible for two invocations of synchronized methods on the same object to interleave.
However, if a non-static synchronized method contains a call to wait(), this releases the thread's ownership of the object's monitor, thus allowing another thread to enter a synchronized method. Am I misunderstanding wait(), or is this not considered interleaving?

This is not considered interleaving.
Only one thread is awake inside the synchronized block at a time.

Related

Does Thread.join() release the lock? Or continue to hold it?

As I understand it, internally obj.join() calls wait(). This means that join() always releases the lock (because wait() always releases the lock after being called).
The API doc explains:
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.
People here on SO say that join() does not release any lock because the API does not mention it explicitly. But this logic seems strange to me.
Here is the main logic from join()'s code:
while (isAlive()) {
wait(0);
}
This site further adds to the confusion (I think they are mistaken):
3) The third difference between the wait() and join() methods is that when a thread calls the wait() method it releases any lock held for the object on which wait() is called, but calling the join() method doesn't release any monitor or lock.
wait releases the monitor held on the object which wait is invoked on, but not any other monitors.
The current thread must own this object's monitor. The thread releases ownership of this monitor and waits [...].
In other words, given the following:
synchronized (a) {
synchronized (b) {
b.wait();
}
}
At b.wait(), the current thread releases b's monitor, but not a's monitor.
If t.join() is implemented using t.wait() internally, then t's monitor is released while waiting, but not any other monitor.
This join implementation is a case of leaky abstraction, by the way. If Thread used a private final Object monitor; to wait on instead, we could say that join released no monitors, even if it used wait internally without us knowing. There would be no reason to document the implementation detail of using wait, because the monitor would be inaccessible to us, so we would not need to know about it.
The reason that we know join uses wait internally is that the people who originally wrote the method chose a monitor which is accessible to us. This created the need to reveal the implementation details. join is not really supposed to release monitors from our perspective, just wait for a thread to complete, but an implementation was chosen which required us to know more about it than we should.
Though the excellent answer from #Radiodef clarifies & elaborates the leaky abstraction shortcoming, in simpler terms to answer #vrinchvucz confusion the answer is,
Yes, when a thread invokes t.join it does acquire and release 'a' monitor lock. That monitor lock is that of the thread t itself since the implementation of join method on Thread class implemented it by using this.wait inside of the synchronized join method which is the leaky abstraction issue that #Radiodef points to.
Thus unless the thread acquires the monitor lock of t itself before it invokes t.join we can say that NO client/user acquired monitor locks are released in the t.join invocation (because the monitor lock in question is NOT any that the client/user code acquired in the thread that invoked t.join).
This since as clearly stated in the docs for Object#wait
Note that the wait method, as it places the current thread into the
wait set for this object, unlocks only this object; any other objects
on which the current thread may be synchronized remain locked while
the thread waits.
Which is why the docs for Thread#join does not mention anything about locks being released while still giving the implementation details regarding the use of this.wait.

What does intrinsic lock actually mean for a Java class?

In order to properly understand the issues and solutions for concurrency in Java, I was going through the official Java tutorial. In one of the pages they defined Intrinsic Locks and Synchronization link. In this page, they say that:
As long as a thread owns an intrinsic lock, no other thread can
acquire the same lock. The other thread will block when it attempts to
acquire the lock.
Also, they mention in the section Locks In Synchronized Methods that:
When a thread invokes a synchronized method, it automatically acquires
the intrinsic lock for that method's object and releases it when the
method returns. The lock release occurs even if the return was caused
by an uncaught exception.
For me this means that once I call a synchronized method from one of the threads, I will have hold of the intrinsic lock of the thread and since
Intrinsic locks play a role in both aspects of synchronization:
enforcing exclusive access to an object's state and establishing
happens-before relationships that are essential to visibility.
would another thread be unable to call another synchronized method of the same class? If yes, then the whole purpose of having synchronized methods is defeated. Isn't it?
Seems you have one misunderstanding (dunno if it caused the wrong conclusion) that no one has pointed out. Anyway, a brief answer:
Intrinsic Lock: Just think it as, every object in JVM has internally a lock. synchronized keywords tries to acquire the lock of the target object. Whenever you synchronized (a) { doSomething; }, what actually happens is
the lock in a is acquired
code within the synchronized block is run (doSomething)
release the lock in a
and I wish you know
public synchronized void foo() {
doSomething;
}
is conceptually the same as
public void foo() {
synchronized(this) {
doSomething;
}
}
Ok, go back to your question, the biggest problem, imho, is :
For me this means that once I call a synchronized method from one of the threads, I will have hold of the intrinsic lock of the thread and since...
It is wrong. When you call a synchronized method, you are not get hold of the lock of the thread.
Instead, that thread will own the intrinsic lock of the object that is "owning" the method.
e.g. in thread1, you called a.foo(), and assume foo() is synchronized. thread1 is going to acquire the intrinsic lock of the object a referring.
Similarly, if AClass.bar() is called (and bar is synchronized and a static method), the intrinsic lock of AClass Class object will be acquired.
So just to repeat my comment above as an answer. Intrinsic locking means that you don't have to create an object to synchronize your methods on. In comparison you can use an extrinsic lock by calling synchronized(myLock) {...}.
This is an excerpt from the book Java Concurrency in Practice: "The fact that every object has a built-in lock is just a convenience so that you needn't explicitly create lock objects"
The book also says:
There is no inherent relationship between an object's intrinsic lock
and its state; an object's fields need not be guarded by its intrinsic
lock, though this is a perfectly valid locking convention that is used
by many classes. Acquiring the lock associated with an object does not
prevent other threads from accessing that objectthe only thing that
acquiring a lock prevents any other thread from doing is acquiring
that same lock. The fact that every object has a built-in lock is just
a convenience so that you needn't explicitly create lock objects. [9]
It is up to you to construct locking protocols or synchronization
policies that let you access shared state safely, and to use them
consistently throughout your program.
But in the footnote it says:
[9] In retrospect, this design decision was probably a bad one: not
only can it be confusing, but it forces JVM implementors to make
tradeoffs between object size and locking performance.
And to answer your last questions: you won't be able to call the synchronized methods from another thread, but you can keep entering from the same thread (intrinsic locks are re-entrant). So you have to imagine locking in this case as serializing method access from different caller threads.
If you use locking improperly and then you introduce liveness hazards, then yes it is defeated. That's why you have to make sure that your concurrent threads are not contending with each other too hard.
As Brian Goetz puts in this blog entry:
In tuning an application's use of synchronization, then, we should try
hard to reduce the amount of actual contention, rather than simply try
to avoid using synchronization at all
A lock can be held by only one thread at a time. That doesn't defeat the purpose; that is the purpose.
Threads mutually exclude each other from simultaneous action in critical sections by acquiring a lock, or mutex. This provides effective atomicity around a series of distinct actions, so that other threads never see intermediate states that might violate consistency guarantees.
Yes, you won't be able to call other synchronized method on the same object, because of the intrinsic lock. Which is at object level, only 1 thread will acquire it.
would I be unable to call another synchronized method of the same class? If yes, then the whole purpose of having synchronized methods is defeated. Isn't it?
No. You can't call other synchronized method on same object for Object level lock and you can't call other static sysnchronized method on same class.
But it does not defeat the purpose of having synchronisation.
If you follow the other documentation page on synchronized methods:
Making these methods synchronized has two effects:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
If you allow two synchronized method to run in parallel. you will bound to get memory inconsistency errors on shared data.
On a different note, Lock provides better alternative synchronized construct.
Related SE question:
Synchronization vs Lock
It doesn't matter whether the synchronized method belongs to the same class or not, what matters is if the caller thread of the method acquires the lock or not, if it does, then it will be allowed enter the critical section because the lock is reentrant.
If it wasn't the case, then a recursive call would cause a deadlock,
fn(){
synchronized(mutex){ // the current thread has already acquired the mutex
fn();
}
}
fn here wont deadlock because the lock is re-entrant, ie ( the thread that's already acquiring the lock can enter and renter the critical section again as long as it is still acquired).
Locks can be divided in two classes - 'reentrant' and 'not reentrant'.
In Java 'synchronized', base implementation of interface Lock (class ReentrantLock), interface ReadWriteLock (class ReentrantReadWriteLock) - are reentrant.
Reentrancy means - one thread can again and again hold the lock.

Is it required to use thread wait() and notify() inside a synchronized block?

In Java, is it required to use thread wait() and notify() within a synchronized block?
No. Java will automatically ensure the marked section is entered by one and only one thread.
http://tutorials.jenkov.com/java-concurrency/synchronized.html
see also this question: java: wait(), notify() and synchronized blocks
Hmm.. seems to be some language issues.
You are not required to use wait and notify in a synchronized block, but if you want to use wait and notify, they must be used within a synchronized block.
in short, yes. The thread must own the object's monitor before calling wait or notify.

About wait() and notify() methods of thread in java

I know the mechanism of wait() and notify() of thread, but I am unable to understand that why wait() and notify() methods should be in synchronized block? Is this mandatory?
Thanks in Advance!
Is synchronized mandatory while invoking wait/notify: Yes
Why?: Consider that synchronizing was not required. That means that a thread A could call notify() exactly at the same time while the other thread B is calling wait()(on the same object). Suppose thread B has executed part of wait() method and is context-switched to serve thread A. So the internal data-structures of wait could be in corrupt state now. Now the notify() method essentially works on the same data-structures, which now is in invalid state. Hence the entire wait/notify could go for a toss. Synchronizing guarantees that no other method could call wait/notify if there is a call to one of them already on.

Why are wait() and notify() declared in Java's Object class?

Why are the wait() and notify() methods declared in the Object class, rather than the Thread class?
Because, you wait on a given Object (or specifically, its monitor) to use this functionality.
I think you may be mistaken on how these methods work. They're not simply at a Thread-granularity level, i.e. it is not a case of just calling wait() and being woken up by the next call to notify(). Rather, you always call wait() on a specific object, and will only be woken by calls to notify on that object.
This is good because otherwise concurrency primitives just wouldn't scale; it would be equivalent to having global namespaces, since any calls to notify() anywhere in your program would have the potential to mess up any concurrent code as they would wake up any threads blocking on a wait() call. Hence the reason that you call them on a specific object; it gives a context for the wait-notify pair to operate on, so when you call myBlockingObject.notify(), on a private object, you can be sure that you'll only wake up threads that called wait methods in your class. Some Spring thread that might be waiting on another object will not be woken up by this call, and vice versa.
Edit: Or to address it from another perspective - I expect from your question you thought you would get a handle to the waiting thread and call notify() on that Thread to wake it up. The reason it's not done this way, is that you would have to do a lot of housekeeping yourself. The thread going to wait would have to publish a reference to itself somewhere that other threads could see it; this would have to be properly synchronized to enforce consistency and visibility. And when you want to wake up a thread you'd have to get hold of this reference, awaken it, and remove it from wherever you read it from. There's a lot more manual scaffolding involved, and a lot more chance of going wrong with it (especially in a concurrent environment) compared to just calling myObj.wait() in the sleeping thread and then myObj.notify() in the waker thread.
The most simple and obvious reason is that any Object (not just a thread)
can be the monitor for a thread. The wait and notify are called on the
monitor. The running thread checks with the monitor. So the wait and notify methods are in Object and not Thread
Because only one thread at a time can own an object's monitor and this monitor is what the threads are waiting on or notifying. If you read the javadoc for Object.notify() and Object.wait() it's described in detail.
The mechanism of synchronization involves a concept - monitor of an object. When wait() is called, the monitor is requested and further execution is suspended until monitor is acquired or InterruptedException occurs. When notify() is called, the monitor is released.
Let's take a scenario if wait() and notify() were placed in Thread class instead of Object class. At one point in the code, currentThread.wait() is called and then an object anObject is accessed.
//.........
currentThread.wait();
anObject.setValue(1);
//.........
When currentThread.wait() is called, monitor of currentThread is requested and no further execution is made until either the monitor is acquired or InterruptedException occurs. Now while in waiting state, if a method foo() of another object anotherObject residing in currentThread is called from another thread, it is stuck even though the called method foo() does not access anObject. If the first wait() method was called on anObject, instead of the thread itself, other method calls (not accessing anObject) on objects residing in the same thread would not get stuck.
Thus calling wait() and notify() methods on Object class(or its subclasses) provides greater concurrency and that's why these methods are in Object class, not in Thread class.
A few of the other answers use the word "monitor", but none explain what it means.
The name "monitor" was coined way back in the 1970s, and it referred to an object that had its own intrinsic lock, and associated wait/notify mechanism. https://en.wikipedia.org/wiki/Monitor_%28synchronization%29
Twenty years later, there was a brief moment in time when desktop, multi-processor computers were new, and it was fashionable to think that the right way to design software for them would be to create object-oriented programs in which every object was a monitor.
Turns out not to have been such a useful idea, but that brief moment happens to be exactly when the Java programming language was invented.
Read here for an explanation of wait and notify.
It would be better to avoid these however in your applications and use the newer java.util.concurrent package.
I will put it in a simple way:
To call wait() or notify() you need to own the object monitor - this means wait() or notify() needs to be present in the synchronized block
synchronized(monitorObj){
monitorObj.wait() or even notify
}
Thats the reason these methods are present in object class
This is because,these methods are for inter thread communication and interthreadcommunication happens by using locks, but locks are associated with objects.hence it is in object class.
Wait and Notify methods are used communication between two Threads in Java. So Object class is correct place to make them available for every object in Java.
Another reason is Locks are made available on per Object basis. 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

Categories

Resources