Lock acquisition order after notify() - java

Suppose thread T1 is waiting to enter a synchronized block, and thread T2 is wait()-ing within the block, and thread T3 calls notify() on the block's monitor.
Is it possible for T1 to enter the block before T2 proceeds? Or does T2 get precedence?

Is it possible for T1 to enter the block before T2 proceeds?
Yes it is possible. The javadoc for Object.wait(int) does not specify that the thread that has been notified takes precedence. In fact it specifies that normal scheduling rules are applied.
"The thread T is then removed from the wait set for this object and re-enabled for thread scheduling. It then competes in the usual manner with other threads for the right to synchronize on the object ..."
This is one of the reasons why you need to code condition variables like this
private boolean condition = ...
private Object lock = new Object(); // mutex for 'condition'
...
synchronize (lock) {
while (!condition) {
wait(lock);
// It is UNSAFE to assume that 'condition' is true now.
}
}

Related

how the synchronized keyword lock the method or block using the object

When we want to lock the block by synchronized statements we pass a object to it , I want to know that how this object lock the block , actually I want to know the mechanism of lock by synchronized keyword.
example :
Object object = new Object();
synchronized (object) {
//do something
}
my question is how object lock the block .
When a thread encounters a synchronized block (which uses objects for synchronization, as in your example) the following happens:
the Java runtime checks if an other thread has already started executing the synchronized block (and is not finished yet) with the same "blocking" object instance
If yes: our thread must wait (it is blocked) until the other thread finishes. After the other thread releases the lock (and no other waiting thread acquires the lock before out thread), ours can enter the block
If no: our thread can immediately enter the synchronized block
The same instance is a very important part, consider the following example:
public void method() {
Object object = new Object();
synchronized (object) {
//do something
}
}
In this example synchronization will effectively never happen, threads will never block. Because each thread creates a new instance before encountering the block. They never use the same.

Does calling interrupt() on a thread create happens-before relation with the interrupted thread

In other words I want to know if changing variable before interrupt is always visible when interrupt is detected inside interrupted thread. E.g.
private int sharedVariable;
public static void interruptTest() {
Thread someThread = new Thread(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// Is it here guaranteed that changes before interrupt are always visible here?
System.out.println(sharedVariable);
}
});
someThread.start();
Thread.sleep(1000);
sharedVariable = 10;
someThread.interrupt();
}
I tried to find answer in Java language specification and in
Summary page of the java.util.concurrent package mentioned in Java tutorial but interrupt was not mentioned.
I know about volatile and other synchronize primitives but do I need them?
Yes, interrupting a thread T2 from a thread T1 creates a happens-before relationship between T1 and T2, as described in the JLS 17.4.4. Synchronization Order:
If thread T1 interrupts thread T2, the interrupt by T1
synchronizes-with any point where any other thread (including T2)
determines that T2 has been interrupted (by having an
InterruptedException thrown or by invoking Thread.interrupted or
Thread.isInterrupted).
Now that only implies that T1 synchronizes-with the detection of the interrupt T2, while you asked about happens-before. Luckily the former implies the latter from 17.4.5. Happens-before Order:
Two actions can be ordered by a happens-before relationship. If one
action happens-before another, then the first is visible to and
ordered before the second.
If we have two actions x and y, we write hb(x, y) to indicate that x
happens-before y.
...
If an action x synchronizes-with a following action y, then we also have hb(x, y).
So you are safe to access sharedVariable knowing that it has (at least) the value written by T1, even without volatile.

Is using ReentrantLock reliable as synchronized?

I searched a lot but was confused with the process of 'ReentrantLock' and normal 'synchronized' .
For example(1):
Object obj = new Object();
synchronized(obj){
//lock is guaranteed to be acquired
}
example(2)
Lock lock = new ReentrantLock();
lock.lock(); //problem here
try{
//dostuff
}
finally{
lock.unlock();
}
My question is:
In example 1: it is guaranteed to acquire a lock on the object using the synchronized keyword.
But
In example 2: is it guaranteed that the lock will be acquired using the lock.lock() method?? or will the thread proceed to the next line for the execution?? without acquiring the lock.
I doubt it because, using threads had resulted in unexpected outcomes for me many times.
Only one thread will acquire the lock: this is the contract of ReentrantLock.
Therefore your example 2 is perfectly thread safe.

Why does 'wait() method within synchronized block' have deadlock possibility?

klocwork JD.LOCK.WAIT issue is reported when an Object.wait() method is called while the method is holding two or more locks.
klocwork says that waiting on a monitor while two locks are held may cause deadlock and the issue should be taken into account.
But I cannot understand why this causes deadlock.
Who can help me understand this issue?
Following code is from klockwork. The JD.LOCK.WAIT issue occurs on line 14 lock.wait();.
String name;
synchronized void waitForCondition(Object lock) {
try {
synchronized(lock) {
name = "aa";
lock.wait(); //line 14
}
} catch (InterruptedException e) {
return;
}
}
Lets say t1 enters the waitForCondition() method. So t1 now has this as a lock. Meanwhile, some other thread has just acquired lock object and is trying call waitForContion().
t2 holds lock but is waiting for this to enter waitForContion().
t1 holds this but is waiting for lock to exit waitForContion().
That is a deadlock. Neither of them can make any progress and are waiting on each other.
To avoid this, one strategy is to make sure any thread has all the resources it needs to complete. Here it means that lock and this can only be acquired together and not otherwise.
Also, when lock.wait() is called, only lock is released while this is not. So, in such a case no thread can call waitForContion() on that object.

Do two synchronized methods execute simultaneously

I have 4 methods (m1, m2, m3 and m4) in a class. Method m1, m2 and m3 are synchronized methods. Also, I have 4 threads t1, t2, t3 and t4 respectively.
If t1 access the m1 method (synchronized method), could t2 thread access m2 method (synchronized method) simultaneously? If not what would be the state of t2?
If t1 access the m1 method (synchronized method), could t2 thread access m2 method (synchronized method) simultaneously?
The synchronized keyword applies on object level, and only one thread can hold the lock of the object. So as long as you're talking about the same object, then no, t2 will wait for t1 to release the lock acquired when it entered m1.
The thread can however release the lock without returning from the method, by calling Object.wait().
If not, what would be the state of t2 ?
It would sit tight and wait for t1 to release the lock (return from the method or invoke Object.wait()). Specifically, it will be in a BLOCKED state.
Thread state for a thread blocked waiting for a monitor lock. A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method or reenter a synchronized block/method after calling Object.wait.
Sample code:
public class Test {
public synchronized void m1() {
try { Thread.sleep(2000); }
catch (InterruptedException ie) {}
}
public synchronized void m2() {
try { Thread.sleep(2000); }
catch (InterruptedException ie) {}
}
public static void main(String[] args) throws InterruptedException {
final Test t = new Test();
Thread t1 = new Thread() { public void run() { t.m1(); } };
Thread t2 = new Thread() { public void run() { t.m2(); } };
t1.start();
Thread.sleep(500);
t2.start();
Thread.sleep(500);
System.out.println(t2.getState());
}
}
Output:
BLOCKED
If the methods are synchronized on the same monitor, then they cannot execute simultaneously in different threads. When the second thread comes to the monitor entry (the start of the synchronized method in this case), it will block until the first thread releases the monitor.
The actual state of the blocked thread in this case, as reported by jconsole, will be something like java.lang.Thread.State: WAITING (on object monitor)
Assuming all methods are normal instance methods, then they will share the same monitor when invoked on the same object. That is, if you had something like:
// Thread 1
A a1 = new A();
a1.m1();
// Thread 2
A a2 = new A();
a2.m2()
then in this case, the second thread will be able to call the method, because it's trying to obtain the implicit monitor of the a2 object, which is not locked by thread 1. But if thread 2 tried to call a1.m2(), then it would block until thread 1 had finished executing m1().
If you have static methods, then they obtain the explicit monitor of the class itself (A.class in my hypothetical-naming case), so will not be blocked by any instance method invocations.
No, it couldn't. That's the only point there is to synchronized: different threads can't do these things simultaneously (You don't have to guard against the same thread doing them simultaneously, because a single thread can't do anything in parallel at all.) The state of the waiting thread is 'waiting for lock'. (With a sufficiently modern JVM you can actually have this state displayed on the console if you ask in the right way.)
If t1 access the m1 method (synchronized method), could t2 thread access m2 method (synchronized method) simultaneously?
No. Thread t2 will wait for Thread t1 to release the lock.
In your same example, t2 can access method m4 which is not synchronized.
Locks In synchronized Methods
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
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
Coming back to your second query:
If not, what would be the state of t2 ?
Thread t2 is in blocked state and waiting for Thread t1 to release the lock.
From java documentation page:
making synchronized method have 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 thread

Categories

Resources