Impact of wait() method on a thread in synchronization block in java - java

synchronized (lockObject) {
// update some value of the common shared resource
lockObject.wait();
}
As on call of the wait() method, the thread will release the lock, I want to know after releasing the lock does it also update the value in the main memory of the shared resource object or it only updates the value after the execution of the synchronized block.

It is a fallacy to think that due to synchronization (e.g. synchronized or volatile) data needs to be written to main memory. CPU caches on modern CPUs are always coherent due to the cache coherence protocol.
An object.wait causes the thread to release the lock. And as soon as another thread sends a notify, the lock is reacquired. The object.wait has no semantics in the Java memory model; only acquire and release of the lock are relevant.
So in your particular case, if a thread does a wait, it triggers a lock release. If another thread would read that state after acquiring the same lock, then there is a happens-before edge between the thread that did the release of the lock (due to wait) and the thread that acquired the lock. And therefore the second thread is guaranteed to see the changes of the first.

In the JLS 17.4.5 it says
The wait methods of class Object (ยง17.2.1) have lock and unlock actions associated with them; their happens-before relationships are defined by these associated actions.
Also, from JLS 17.4.4:
An unlock action on monitor m synchronizes-with all subsequent lock actions on m (where "subsequent" is defined according to the synchronization order).
If a thread waits it gives up the lock so that other threads can act. It only makes sense that any changes the thread made before waiting (which triggers an unlock action) should be visible to other threads acquiring the lock.

Related

What if notifyAll is called at the start of critical section

What if notifyAll is called at the start of critical section where lock is not released and released at the end of cs(critical section). What will happen to waiting threads?
Do the notifyAll will get heard by all threads and all thread will try to get lock and get unsuccessful(since notify/notifyAll do not release lock) and keep on trying until they get the lock?
So, what difference it makes to call notify at the start of critical section or at the end ?why it is recommended to call notifyAll at the end of cs?
When you call notifyAll() all waiting threads are reactivated and try to acquire the lock on the object on which you called notifyAll().
IMHO the correctness of your code is not sacrificed - no other thread can acquire the lock as long as it is held by the current thread (the one calling notifyAll()).
But the performance will suffer - waking up threads takes processor resources, having them try to acquire the lock takes processor resources, waiting for the release of the lock takes processor resources.
Often the advice to call notifyAll() at the end of a critical section is fulfilled trivially because your thread is doing some processing in a critical section and at the end of that processing it notices that it should notify waiting threads that they can continue. In that case notifying other threads that they can continue before being sure that this is really the case doesn't make any sense.

How does multiple threads acquire and release lock in synchronized methods and synchronized blocks in java?

How does the java thread acquire a lock on a monitor used in synchronized block or monitor used in synchronized methods?
I read on multiple posts that in case of biased locking this information is stored in the object header using CAS operation and in case of contended situation wait set queue/ monitor queue is used but eventually lock marked in the object header only.
If this is the case then how is lock released? How object is marked free for acquiring a lock by another thread? are wait and notify methods used internally for this? If this is the case then why is making monitor null inside the synchronized block does not throw any exception.
The below example works perfectly fine, I was expecting NullPointerException assuming the end of the synchronized block will try to mark lock property to free the lock.
Example:
Object monitor = new Object();
synchronized (monitor){
System.out.println("before null");
monitor =null;
System.out.println("after null");
}
System.out.println("successfully Exited");
In case of biased locking: if the lock is biased towards a certain thread, no CAS is needed; just a volatile write. Biased lock information is kept in the mark word of the object header. Biased locking is going to be removed from JDK 15.
If a lock is contended, the object-monitor is used for synchronization. By default the object monitor is deflated, but if there is contention or you do a wait/notify, then the monitor gets inflated and is attached to the object.
On Linux blocking behavior is implemented using a wait-queue. So when a thread needs to wait for a lock, it is removed from the scheduler and added to the wait queue. When a lock unlocks, the thread on the wait queue is reinserted back into the scheduler.
The reason why the code doesn't throw an exception is that the monitor is read only once when the synchronized block is entered.
PS: It could be that your lock get completely removed due to lock elision. If the JIT can provide no other thread can acquire that lock, there is no point in synchronizing.

Can another thread enter a monitor, while the waiting one is notified?

I am investigating Java concurrency and I've found one interesting question which I cannot answer.
For example, I have three threads: ThreadA, ThreadB and ThreadC. ThreadA enters the monitor, and invokes method wait(). Then ThreadB enters the same monitor, invokes method notify() and continue owning the monitor during some period of time. While ThreadB is owning the monitor, ThreadC tries to acquire the monitor too. My question is whether ThreadC can acquire the monitor earlier then ThreadA when ThreadB release it or not? If it can, why? Which conditions should be followed to reproduce it?
As per the Javadoc on Object.notify():
The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.
So there exists the possibility that ThreadC owns the monitor before ThreadA. There is no defined order in which any of the threads enter/obtain the monitor, nor is there any priority or fairness mechanism in place for standard synchronization. All it really guarantees is that for a given lock object, only on thread will be in the synchronized block at once.
Given this fact, careful design considerations should go into how threads obtain the lock and for how long. A thread that repeatedly attempts to acquire a lock (acquire and then release but then acquire again) can cause another thread to be locked out indefinitely (called thread starvation).
Using ReentrantLock with a fairness policy can partially overcome this issue at some performance cost (its slightly slower than traditional synchronization).

Locking by synchronization

Hi my question is how synchronization works?
In simple words we know that if a thread entered in a synchronization block by acquiring lock on any reference, than no other thread acquire that lock until first one exit from synchronized block.
But my question is if the thread acquired a lock on a reference and execute methodA() in that method there is a synchronized block, than can other thread acquire a lock on same reference and execute methodB(), there is also a synchronized block in it?
Synchronization is for mutual exclusion
Whenever you synchronize on an object, a lock is obtained on the monitor of that object.
Image Source: Thread synchronization
As the image shows as whenever a thread acquires a lock on monitor then it becomes the owner thread and no other thread can obtain lock on same monitor unless the owner thread enters wait state or releases the lock.
That said another point to keep in mind is that locks that are used in synchronized blocks are Reentrant, which means that if Thread 1 is the owner of the lock and same thread again tries to gain lock of which it is owner then Java will allow that.
Ok, than i have a issue. synchronized(b){ try{ b.wait();
}catch(InterruptedException e){} now as i acquired a lock on b object,
it means no other thread can acquire a lock on b object.
On calling wait(), the owner thread releases the lock and goes in Wait Set as shown in diagram. After that someone else from Entry set can get the lock.
I believe that the second lock will have to wait till the first lock has been released.
Have a look at the link Java synchronized references for more information.
Synchronization is very simple
One Thread locks any number of objects.
Only one thread can lock a given object at a given time.
When attempting to lock an object that is already locked by another thread, a thread has to wait until the object is released.
A Thread in wait state releases the locks it holds until it exists the wait state (at which time it attempts to reacquire the locks previously held).
In java, a lock is acquired using a synchronized block.
To answer your question: 2 threads can never acquire a lock on the same object at the same time.

memory visibility on lock acquirement

Does memory visibility depend on which monitor is used? Lock B is acquired after lock A is released, is it enough for memory visibility?
for example following code:
int state; // shared
// thread A
synchronized (A) {
state += 1;
}
Thread.sleep(10000000);
// thread B
Thread.sleep(1000);
synchronized(B) {
state += 1;
}
threads are started in the same time and thread B sleep time may be arbitrarily high, just to ensure that it is executed after thread A used state variable. Thread A sleep time is used to ensure that thread does not finish before thread B uses state shared variable.
UPDATE
From http://www.ibm.com/developerworks/library/j-jtp03304/
When a thread exits a synchronized block as part of releasing the associated monitor, the JMM requires that the local processor cache be flushed to main memory.
Similarly, as part of acquiring the monitor when entering a synchronized block, local caches are invalidated so that subsequent reads will go directly to main memory and not the local cache.
If this is true then I see no reason for state variable not to be visible to thread B
Further, however they say that monitor should be the same, but it is not implied from aforementioned statements.
This process guarantees that when a variable is written by one thread during a synchronized block protected by a given monitor and read by another thread during a synchronized block protected by the same monitor, the write to the variable will be visible by the reading thread.
It seems that process of local memory flush is not so straightforward as it is described in the first statement and may not happen on every lock release?
Yes, it depends. You can read this doc about this. Relevant section is "17.4.4. Synchronization Order":
An unlock action on monitor m synchronizes-with all subsequent lock actions on m (where "subsequent" is defined according to the synchronization order).
You see, a concrete monitor object m is specified there. If monitors are different, then you are not getting synchronizes-with relationship, hence, you do not get happens-before relationship (from the 17.4.5):
If an action x synchronizes-with a following action y, then we also have hb(x, y).
So, your updates will be performed out of order with possible missing updates.
Does memory visibility depend on which monitor is used? Yes.
Lock B is acquired after lock A is released, is it enough for memory visibility? No.
The two threads have to synchronize on the same monitor in order to see each others' writes. In your example, both threads could see state having the value 1. No matter what sleep intervals you insert. It of course depends on the implementation of the JVM you're using and different JVMs could yield different results. Basically, you have unsynchronized access to a field and that should always be avoided (because it's not deterministic what value state has).
Read more in the excellent chapter on the Memory Model in the Java Specification.

Categories

Resources