How two threads can take lock on same object at a time? - java

I was reading Java Concurrency in Practice.
SO it is written that
When thread A executes a synchronized block, and subsequently thread B enters a
synchronized block guarded by the same lock
How can two thread take lock on same object at a time?
Thanks.

"When thread A executes a synchronized block, and subsequently thread B enters a
synchronized block guarded by the same lock" .
There will only be one lock. Thread B can get hold of the lock only when Thread A releases the lock. "subsequently". The author wants to say that the changes made by Thread A on the same object will be visible to Thread B.

They mean B enters lock after A released it

Each object has lock. Just before a thread enters the synchronized block to execute the code, it acquires the lock. When the thread has finished executing the block, it releases the lock. The second thread cannot acquire the lock during this time. It acquires the lock once it has been released by the first thread.

Related

Intrinsic locks and Synchronization in Java

As per Oracle docs for Intrinsic Locks and Synchronization :
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.
My question is:
what does happens-before relationships here means in synchronization context? Does this mean that once a thread executes a synchronized block all the changes are flushed to main memory before other thread comes and reacquire the lock?
Also I have another question:
Suppose thread1 has acquired the lock and is executing the synchronized block.
Is it possible for JVM/thread scheduler to force the thread1 to another state say wait such that it will release the lock and another thread say thread2 will acquire the lock? Now after some time thread1 can again go into running state and start from where it lost the lock.
what does happens-before relationships here means in synchronization
context?
This relationship is simply a guarantee that memory writes by one specific statement are visible to another specific statement. In this case, it means when you write some thing in the synchronized block, then other threads which enter the synchronized block will notice this change.
Is it possible for JVM/thread scheduler to force the thread1 to
another state say wait such that it will release the lock and another
thread say thread2 will acquire the lock?
No, while the thread can release the lock by calling wait.

java: If notify() is always called before the lock release, how could a waiting threads acquire this same lock?

I think that I already know the answer to that question, however, I would like to read your opinions to make sure that I really understand how java thread's state machine (or diagram) works.
Imagine that Thread A runs the notify() just before return a given value:
public class baz{
// Thread B runs this:
public synchronized void bar(){
wait();
}
// Thread A runs this:
public synchronized int foo(){
notify();
return 11;
}
}
notify() will be called before Thread A releases the lock (that will occurs "after" the return 11; statement).
So, how could a Thread B, that is waiting for this lock (via wait() method), acquire the lock that is still held by Thread A?
Note that, when thread B is notified the lock has not yet been released by Thread A.
So what I think of this situation is the following:
After calling wait(), Thread B will change its state from Running to Waiting.
After receiving the notification (from Thread A notify() method), Thread B will return from wait(), change its state to Runnable and try to acquire the lock. Since the lock is not yet released by Thread A, Thread B will be blocked on the object's monitor and pass its state from Runnable to Blocked.
Eventually, after Thread A releases the lock, Thread B will acquire the lock and pass its state from Blocked to Running.
Is this right? What I want to understand with this question is what happens to a thread that returns from a wait() which is synchronized by an already acquired lock.
Yes, your explanation is correct.
When you call wait() on an object, the calling thread will be added to the object's wait set. When it is notify()ied, it will be removed from that wait set, and perform a lock action on the object (it's within a synchronized block on that object). That lock action will block the current thread until it is complete, ie. locked the object monitor.
This is the exact same behavior that two threads would have when trying to enter a synchronized block on the same object. The first thread to reach would lock the object monitor, completing the lock object immediately. The other thread blocks until its lock action is complete, ie. after the first thread unlocks the monitor.

doing lot of work after notify() will cause wait() become busy wait?

if i have the below piece of code
synchronized (this)
{
System.out.println("Waiting for return key.");
scanner.nextLine();
System.out.println("Return key pressed.");
notify();
Thread.sleep(5000);
}
After notify, I am calling sleep which means, I have notified the waiting thread but not relinquished the lock, what happens now.. After notifying the waiting thread would have been woken up but not able to acquire the lock, so from here on-wards, is it a busy wait? since we are not going to call notify again.
Same question goes with notify and notifyall, after one thread woken and acquired lock, is that all other thread waiting becomes busy wait?
wait() doesn't busy-wait, but it does "compete in the usual manner with other threads for the right to synchronize on the object" once notified.
A call to notify wakes up one thread that is currently waiting on the object's condition queue which then tries to reaquire the lock which is still held by the calling thread at that point of time. So the situation is comparable to a thread that wants to enter a synchronized block that is currently executed by another thread. The thread is not doing a busy-wait, it is just blocked until it can aquire the lock.
When the thread that called notify releases its lock, the other thread can be unblocked and continue to work.
The same is true for notifyAll, but it wakes up all threads that are waiting on the object's condition queue. As only one of them can acquire the lock, the others stay blocked until they get the lock - one after the other. This and because thread-awaking signals may happen spontaneous it is required to always call wait within a conditional loop:
synchronized (lockObject) {
// ...
while (!condition) {
lockObject.wait();
}
// object is now in desired state
}
See also: Java Concurrency in Practice, Chapter 14.2
A thread can wait on an object only when IT OWNS the object's monitor. Once the first thread notifies, the second thread wakes up but doesn't do anything. The only thing that happens here is that "The thread will be removed from the list of threads waiting on the object . It is left to the OS to schedule its execution. The OS might choose NOT to execute it for sometime. The thread doesn't busy-wait. It will just be in the set of threads which are waiting to be scheduled.
As #Holger points out, any thread which calls wait() releases the lock on the object. Once it is notified, it has to "compete" and reacquire the lock on the object. Reacquiring of lock doesn't happen when notify() is called by the thread which holds the lock. It happens when that thread exits its synchronized block.

Understanding multi-threading

I just have a question in regards to threads that run concurrently and the lock they have on an object. From what I understand is that the thread that calls the wait() method will go on a waiting list and allows another thread from a blocked list to take over the lock on and object(within synchronized code).
If this thread that now has the lock on the object calls the notify() method it wakes up the thread that called wait() and it is moved to the blocked list.
What happens to the thread that calls the notify() method. Does it still have a lock on the object or does it now go on a waiting list?
regards
Only one thread can hold the lock for an object. The wait() and notify() methods must be called while the thread holds the lock on the object you call these methods on; if they don't (for example, because you didn't synchronize on the object), you'll get an IllegalMonitorStateException.
When you call wait(), then the thread gives up the lock and goes on a waiting list (stops executing). When wait() returns, the thread will have obtained the lock again. However, the thread that calls notify() is still holding the lock, so the waiting thread will not resume before the notifying thread exits the synchronized block or method so that it releases the lock on the object.
By calling notify() the thread is not giving up the lock on the object.
A possible sequence of events would be:
Thread 1 goes into a synchronized block, obtaining the lock for the object
Thread 1 calls wait() on the object, giving up the lock, stops executing
Thread 2 goes into a synchronized block, obtaining the lock for the object
Thread 2 calls notify() on the object, but still holds the lock
Thread 1 is awakened and tries to obtain the lock, but it can't because Thread 2 still has it (so Thread 1 has to wait for the lock)
Thread 2 exits the synchronized block and releases the lock
Thread 1 can now obtain the lock and returns from wait()
The notifying thread still owns the lock. See doc section 17.14 (bottom of the page):
The notify method should be called for an object only when the current thread has already locked the object's lock. If the wait set for the object is not empty, then some arbitrarily chosen thread is removed from the wait set and re-enabled for thread scheduling. (Of course, that thread will not be able to proceed until the current thread relinquishes the object's lock.)
No, it will release the lock by leaving a synchronized block or returning from a synchronized method. It will not go back to the waiting list until calling wait() again.

Method Synchronization

When we declare a method synchronized then how it is known by second thread that the synchronized section of code used by the first thread is completed and how second thread can use that synchronized section of code?
The thread scheduler tells the second thread. When a thread exits a synchronized block stuff happens in this order:
The exiting thread releases its lock.
The lock tells the thread scheduler that it was released.
The thread scheduler changes the state of the threads waiting on that lock to "running".
The running threads race to acquire the lock, one of them wins, the rest go back to waiting.
The scheduler decides which threads to run and what order to run them in and when to context-switch, so it influences which thread gets the lock, but it doesn't directly hand the lock over to the next thread in line. (Who knows, maybe some implementation does, but you can't count on that behavior in general.)
Java uses an internal construct called a monitor to manage synchronization, basically when thread 1 enters a synchronized method, it takes control of the monitor, similarly when it is finished it releases the monitor. Any threads that arrive while the monitor is currently held are blocked until the monitor is released. Then they enter the synchronized method.
here is more information on monitors:
http://en.wikipedia.org/wiki/Monitor_(synchronization)
When it is a non-static method then this is equivalent synchronizing over this:
public synchronized void xyz() { ... }
is equivalent to
public void xyz() {
synchronized(this) {
...
}
}
When it is a static method then it is synchronized over class object instead.
When thread A enters synchronized method, It acquires a LOCK on the Object calling the method, so any other Thread cannot call the synchronized method using that particular object. However any Thread B can call that synchronized method using some other object of the same class.
So once Object is Locked, No thread can call synchronized method using that object until The previous thread release the Lock. and previous thread will release the lock when it has finished executing the synchronized method.
In the mean time if Thread B and Thread C have invoked the same synchrinized method using the same previous object, then they will start waiting for Thread A to release Lock on Object. When Thread A will release Lock on the Object, then Thread B OR Thread C can start executing, There is no guarantee which one will go first. The other one will continue waiting.
Have a look at oracle documentation page to understand concepts clearly.
Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.") 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.
Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them.
A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. 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.
Javaword article by Bill Venners clearnly explains what actually happening under the hoods.
Two opcodes, monitorenter and monitorexit, are used for synchronization blocks
When monitorenter is encountered by the Java virtual machine, it acquires the lock for the object referred to by objectref on the stack. If the thread already owns the lock for that object, a count is incremented.
Each time monitorexit is executed for the thread on the object, the count is decremented. When the count reaches zero, the monitor is released.
Once the monitor is released, one of the waiting threads will acquire the monitor and above process will be repeated again.
Have a look at related SE questions:
What does 'synchronized' mean?
How Synchronization works in Java?

Categories