In this simple example I have two synchronized (theLock) that are accessed by different threads
public class Main {
public static void main(String[] args) throws InterruptedException {
System.out.println("start");
final Object theLock = new Object();
synchronized (theLock) {
System.out.println("main thread id : " + Thread.currentThread().getId());
new Thread(() -> {
System.out.println("new thread id : " + Thread.currentThread().getId() + ". Inside thread");
// before entering this section new thread should be blocked as `theLock` is already acquired
synchronized (theLock) {
System.out.println("inside synchronized");
theLock.notify();
}
}).start();
theLock.wait();
}
System.out.println("end");
}
}
Why the newly created thread can access to synchronized (theLock) section inside? As far as I understand, theLock is already acquired by the main thread and the new one should block forever. Instead I see that it enters to synchronized as well.
Here is an output
start
main thread id : 1
new thread id : 13. Inside thread
inside synchronized
end
The call to wait() releases the lock. Per wait() Javadoc (bolding mine):
Causes the current thread to wait until another thread invokes the
notify() method or the notifyAll() method for this object. In
other words, this method behaves exactly as if it simply performs the
call wait(0).
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.
Related
This question was asked to me in an interview. Before I had told him this,
Once a thread enters any synchronized method on an instance, no other
thread can enter any other synchronized method on the same instance.
Consider the snippet:
Q1:
public class Q1 {
int n;
boolean valueSet = false;
synchronized int get() {
while (!valueSet)
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
System.out.println("Got: " + n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n) {
while (valueSet)
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
}
}
Producer1:
public class Producer1 implements Runnable {
Q1 q;
Producer1(Q1 q) {
this.q = q;
new Thread(this, "Producer").start();
}
#Override
public void run() {
int i = 0;
while (true) {
q.put(i++);
}
}
}
Consumer1
public class Consumer1 implements Runnable {
Q1 q;
Consumer1(Q1 q) {
this.q = q;
new Thread(this, "Consumer").start();
}
#Override
public void run() {
while (true) {
q.get();
}
}
}
PC1:
public class PC1 {
public static void main(String args[]) {
Q1 q = new Q1();
new Producer1(q);
new Consumer1(q);
System.out.println("Press Control-C to stop.");
}
}
So, he asked as soon as you have created this thread new Producer1(q), then according to you, the synchronized int get() method must have been locked by the same thread, i.e, by new Producer1(q) when it accessed synchronized int put(). I said yes.
But I checked in eclipse, get is callable by new Consumer1(q). The program works perfect.
Where am I going wrong?
O/P:
The call to wait() will release the monitor for the time waiting.
That's what is documented for Object.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.
Once a thread enters any synchronized method on an instance, no other
thread can enter any other synchronized method on the same instance.
What you forgot to add here is "except if the lock is released".
...and it is the case in your example, when calling wait.
The documentation specify :
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.
Since the lock is released, you step in the other method (and the condition is true because the boolean was modified). Once in the other method, you release the lock again, then call notify and you wake up the old thread which terminates (re-modify boolean to pass the condition in other method, and notify). That way you step between both methods ad-infinitum.
wait() and notify() is acts as a signal between threads, to control the threads to do or to not do the stuff.
The program works perfect because here 2 threads (Producer, Consumer) which fight for the one lock (monitor). When Consumer aquires the lock (Q1 object) then Producer is waiting for the lock. When Consumer finishes his work it release the lock. Consumer releases the lock also when wait() method has been called, because wait() sets thread to Waiting state with lock release. It's time for Producer to aquire the lock and does his work. When Producer thread notify() calls then Consumer continue his work (when aquired the lock). The same is right for Producer.
Resume: Q1 object is a lock for all threads. If it aquired someone then others are blocked and the answer is - it not possible to get an access at the same time to the get(), put() methods more then 2 threads.
I think that the question is ambiguous. (E.g., what does "accessible" mean?)
IMO, a good interview question should not have a right answer and a wrong answer. A good interview question should be a conversation starter, that gives you an opportunity to show how much you know about the subject.
When I am asking the interview questions, I like a candidate who can see through the question, and get down to the underlying mechanism. E.g.,
What the JLS guarantees is that no two threads can be _synchronized_
on the same instance at the same time...
Then we could explore questions like, how could two threads enter the same synchronized method at the same time? (e.g., synchronized on different instances), how could two threads be in the same synchronized method for the same instance at the same time (one of them could be in a wait() call), ...
A thread can not access a synchronized block of code unless it has aquired a lock on the object that guards the block. In your case, the synchronized keyword uses the lock of the object in which it has been declared. So as long as a thread is executing get(), no other thread can execute the put().
If you apply this, when put() sets the value, it notifies consumer which accepts the value. The code should work even after you have removed the wait() and notify() calls from both get and put methods
I was just curious is it possible that a thread T1 say executes a synchronization block partially and then releases the lock on the object and another thread T2 executes the same block? Something like this:
line1: synchronized(this){
line2: if(INSTANCE == null)
line3: INSTANCE = new Object(); //say a variable is initialized
line4: return INSTANCE;
line5: }
Is it possible that thread T1 acquires a lock on current object (this) and executes line1 and line2. Then thread T1 is preempted by thread T2, T1 releases lock and T2 acquires lock on this and executes the same block (all the lines1 to 5). Then thread T1 again takes the lock and continues executing from line3?
Basically, T1 will see INSTANCE as null and so will T2 and each will create a new Object.
If this is not possible can someone explain why not?
Addendum:
Thanks everyone for your answer. My question was a bit misleading. What I am exactly asking, is it possible that once a thread is executing a synchronized block it can release the lock before the entire block is executed (not by explicitly calling wait() but something which is process, CPU dependent)? Is there a contract in JLS or a JVM guarantee that once a thread starts executing a synchronized block the lock on the object is not released until the end of the block? My understanding is synchronization guarantees no 2 threads can simultaneously execute the block (or other synchronized method/block) but the lock is hold until the end of the block is reached? It's kind of obvious but is it specified in the JLS?
Thread preemption doesn't cause the preempted thread to release its locks. If it did, locks would be worthless. The whole point of a synchronized block is that it will disallow other threads from synchronizing on the same object until the thread releases the lock (by leaving the synchronized block).
Even if a thread is preempted, it won't release a lock. The lock is still held. If another thread comes along, it will block (stop running) until the lock is released, even if the original thread gets preempted several times before it releases the lock. Basically almost any kind of lock has some storage in the heap that gets written to indicate there's a lock. It's permanent until the thread or the system writes a different value to indicate the lock is free.
It is of course possible to write code that allows access to an instance or field without ever taking the lock, but that's a coding error. It's also possible for the original thread to exit the block early (say it throws an exception) -- this releases the lock, and other threads can continue as normal.
I'm pretty sure it's not possible for a second thread to enter the synchronize block before the first one has executed the entire block. On obtaining the lock on the object, all other threads attempting to enter the synchronized code will be blocked.
See more information here: http://tutorials.jenkov.com/java-concurrency/synchronized.html
Basically you can use Locks objects. Lock objects can allow you to sequentially apply and release locks on multiple locks line by line.
A very good tutorial on how to implement it here
Check out below code:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class test2{
private static Object instance = null;
private static test2 t = new test2();
private static Lock lock = new ReentrantLock();
public static void main(String[] args) {
A a = new A();
B b = new B();
a.setName("Thread-A");
b.setName("Thread-B");
a.start();
b.start();
}
public Object getObj(){
try {
lock.lock();
System.out.println("Begin Current thread: "+ Thread.currentThread().getName());
if(instance == null){
if(Thread.currentThread().getName().equalsIgnoreCase("Thread-A")){
lock.unlock();
while(instance==null){
System.out.println(Thread.currentThread().getName() +" : instance is null");
}
while(true){
if(!lock.tryLock()){
System.out.println(Thread.currentThread().getName() + " waiting for re lock");
}else{
lock.lock();
break;
}
}
}
instance =new Object();
System.out.println("End Current thread: "+ Thread.currentThread().getName());
if (((ReentrantLock) lock).isHeldByCurrentThread()) {
lock.unlock();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return instance;
}
public static class A extends Thread{
#Override
public void run() {
while(true){
if(t.getObj() != null){
break;
}
}
}
}
public static class B extends Thread{
#Override
public void run() {
while(true){
if(t.getObj() != null){
break;
}
}
}
}
}
Output
Begin Current thread: Thread-A
Thread-A : instance is null
Begin Current thread: Thread-B
Thread-A : instance is null
End Current thread: Thread-B
Thread-A waiting for re lock
End Current thread: Thread-A
I'm now trying to add an update checking module into my program. The method is processing a website for update informations. But in some situations the website is not accessable, and the program stops checking in 0.5 seconds. To make this possible, I wrote these code:
int[] lock = new int[0];
boolean fileListGot = false;
Thread downloadFile = new Thread() {
public void run() {
synchronized (lock) {
fileList = HttpFetcher.fetch("http://*****/****");
fileListGot = true;
lock.notify();
}
}
};
synchronized (lock) {
downloadFile.start();
lock.wait(500);
}
return fileListGot;
But the program doesn't stop after 0.5 seconds. What the wrong with the program? And how to use Object.wait(long)?
Read the Object.notify javadocs - the important part being "The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object. "
The main thread acquires the monitor of lock. It starts the worker thread. The worker thread attempts to gain lock's monitor, but cannot. The main thread then calls lock.wait(500) and so loses the monitor. The worker thread then gains the monitor and proceeds. If the download is still going on after 500ms, wait returns and the main thread attempts to gain the monitor, but it is still owned the worker thread.
You don't need to hold the monitor when downloading the file, only when mutating the shared variables - try this instead
public void run() {
T temp = HttpFetcher.fetch("http://*****/****");
synchronized (lock) {
fileList = temp;
fileListGot = true;
lock.notify();
}
}
where T is the appropriate type for fileList
You enter synchronized block then start a thread. The thread's run tries to enter synchronized block and waits forever because you have already taken the same lock from another thread.
Move downloadFile.start() away from synchronized block.
When we call either lock.lock() or try to enter a synchronized block then our thread blocks if some other thread has already taken that lock. Now my question is, when we look at the implementation of lock.lock() it delegates acquiring lock to AQS which actually parks the current thread (so that it cannot be scheduled further by scheduler).
Is it the same case with synchronized blocking also?
I even think my thread status are also different. For example, if my thread is blocked on synchronized block it will be BLOCKING while if I have called
lock.lock(), then it will be WAITING. Am I right?
My Concern is the difference between the below two locking strategies in aspects of Thread.status and performance improvement by parking instead of busy waiting
ReentrantLock.lock();
synchronize { /*some code */ }
BLOCKING - is blocked on a resource, cannot be interrupted
WAITING - is blocked on a resource, but can be interrupted or notified or unparked.
As you can see WAITING is better for control from another processed. e.g. if two threads are deadlocked you could break a lock() with an interrupt. With a two thread using synchronized you are stuck.
The behaviour of the synchronized vs lock is very similar and the exact details change between major revisions.
My advise is to use
synchronized for simpler code where you need thread safety but have a very low lock contention.
use Lock where you have identified you have lock contention, or you need additional functionality like tryLock.
If you do
final Lock lock = new ReentrantLock();
lock.lock();
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
lock.lockInterruptibly();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
Thread.sleep(100);
System.out.println(t + " is " + t.getState());
lock.unlock();
prints
Thread[Thread-0,5,main] is WAITING
Thread.State states
Thread state for a waiting thread. A thread is in the waiting state due to calling one of the following methods:
Object.wait with no timeout
Thread.join with no timeout
LockSupport.park
A thread in the waiting state is waiting for another thread to perform a particular action. For example, a thread that has called Object.wait() on an object is waiting for another thread to call Object.notify() or Object.notifyAll() on that object. A thread that has called Thread.join() is waiting for a specified thread to terminate.
Calling upon lock or lockInterruptibly will put the thread in WAITING state:
Thread state for a waiting thread. A thread is in the waiting state due to calling one of the following methods:
Object.wait with no timeout
Thread.join with no timeout
LockSupport.park
The following code starts four threads, first two (A,B) run the same code and lock some monitor via the lock method. The other two (C,D) also run the same code, but they lock some another monitor via the lockInterruptibly method:
public static synchronized void dumpThreadState(List<Thread> threads) {
System.out.println("thread state dump start");
for (Thread t: threads) {
System.out.println(t.getName()+" "+t.getState());
}
System.out.println("thread state dump end\n");
}
public static void main(String[] args) throws InterruptedException {
final Lock lock = new ReentrantLock();
final Lock anotherLock = new ReentrantLock();
List<Thread> threads = new LinkedList<Thread>();
Runnable first = new Runnable() {
#Override
public void run() {
try {
lock.lock();
}
catch (Exception ex) {
System.out.println(Thread.currentThread().getName()+" processing exception "+ex.getClass().getSimpleName());
}
while (true);
}
} ;
Runnable second = new Runnable() {
#Override
public void run() {
try {
anotherLock.lockInterruptibly();
}
catch (InterruptedException ex) {
System.out.println(Thread.currentThread().getName()+" was interrupted");
}
while (true);
}
};
threads.add(new Thread(first,"A"));
threads.add(new Thread(first,"B"));
threads.add(new Thread(second,"C"));
threads.add(new Thread(second,"D"));
dumpThreadState(threads);
for (Thread t: threads) {
t.start();
}
Thread.currentThread().sleep(100);
dumpThreadState(threads);
System.out.println("interrupting " + threads.get(1).getName());
threads.get(1).interrupt();
dumpThreadState(threads);
System.out.println("interrupting " + threads.get(3).getName());
threads.get(3).interrupt();
Thread.currentThread().sleep(100);
dumpThreadState(threads);
for (Thread t: threads) {
t.join();
}
}
It outputs:
thread state dump start
A NEW
B NEW
C NEW
D NEW
thread state dump end
thread state dump start
A RUNNABLE
B WAITING
C RUNNABLE
D WAITING
thread state dump end
interrupting B
thread state dump start
A RUNNABLE
B WAITING
C RUNNABLE
D WAITING
thread state dump end
interrupting D
D was interrupted
thread state dump start
A RUNNABLE
B WAITING
C RUNNABLE
D RUNNABLE
thread state dump end
As it can be seen the thread locked via the lock method can not be interrupted, while thread locked with lockInterruptibly can.
In the other example three threads are started, the first two (A,B) run the same code and lock upon the same monitor via the synchronized block. The third thread locks on another monitor but waits via the wait method:
public static void main(String[] args) throws InterruptedException {
final Object lock = new Object();
final Object anotherLock = new Object();
List<Thread> threads = new LinkedList<Thread>();
Runnable first = new Runnable() {
#Override
public void run() {
synchronized(lock) {
while (true);
}
}
} ;
Runnable second = new Runnable() {
#Override
public void run() {
synchronized(anotherLock) {
try {
anotherLock.wait();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
};
threads.add(new Thread(first,"A"));
threads.add(new Thread(first,"B"));
threads.add(new Thread(second,"C"));
dumpThreadState(threads);
for (Thread t: threads) {
t.start();
}
Thread.currentThread().sleep(100);
dumpThreadState(threads);
for (Thread t: threads) {
t.join();
}
}
It outputs:
thread state dump start
A NEW
B NEW
C NEW
thread state dump end
thread state dump start
A RUNNABLE
B BLOCKED
C WAITING
thread state dump end
Thread C ended up in WAITING state while thread B ended up in BLOCKING 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.
EDIT:
Here is a real nice UML diagram of thread states.
Parking a thread and synchronized blocking are very different. When you try and enter a synchronized block, you are explicitly attempting to acquire a monitor on an object instance. If you can not acquire the monitor, your thread will go into the BLOCKING state until the monitor is available. Parking is more similar to the Object.wait() method in that the code knows that it can't continue until some other condition becomes true. There's no sense in blocking here because it would be fruitless because my condition for continuing on is currently true. At this point I go into the WAITING or TIMED_WAITING (depends on how the wait is issued) state until I am notified (via something like notify(), notifyAll() or unpark()). Once my condition becomes true I come out if my wait state and then probably attempt to acquire monitors and go into BLOCKING if I need them. If I get my monitors, I go into RUNNING and continue on my merry way
So waiting is really about knowing that I can't do something and having some other thread notify me when it thinks I can. It can lead to blocking after I wake up though. Blocking is just competing for access to a monitor without an explicit other prerequisite condition.
When lock() is called on a Lock instance, the calling thread is actually put into a wait state and is not blocking. The benefit here is that this wait state can be interrupted and this helps to avoid deadlocks. With something like the Lock class, you have a bunch of options on desired waiting behaviors via tryLock(), tryLock(long,TimeUnit), lock() and lockInterruptibly(). You can specify things like how long you want to wait and if you can be interrupted via which method you call. With synchronized code, you don't have such options. You're blocking and you're stuck blocking until some thread gives up the monitor you want and if it never does, you are deadlocked. That's why since Java 5 and the concurrent package, you should avoid using the synchronized keyword and instead try and implement similar semantics with things like Lock and Condition.
I wrote this program to check if a thread t1 holding lock on two different objects :
Lock.class and MyThread.class goes into waiting mode on MyThread.class instance using MyThread.class.wait().It does not release lock on Lock.class instance. why so ? I have been thinking that once a thread goes into wait mode or it dies it releases all the acquired locks.
public class Lock {
protected static volatile boolean STOP = true;
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
Thread t1 = new Thread(myThread);
t1.start();
while(STOP){
}
System.out.println("After while loop");
/*
*
*/
Thread.sleep(1000*60*2);
/*
* Main thread should be Blocked.
*/
System.out.println("now calling Check()-> perhaps i would be blocked. t1 is holding lock on class instance.");
check();
}
public static synchronized void check(){
System.out.println("inside Lock.check()");
String threadName = Thread.currentThread().getName();
System.out.println("inside Lock.Check() method : CurrrentThreadName : "+ threadName);
}
}
class MyThread implements Runnable{
public MyThread() {
}
#Override
public void run() {
try {
System.out.println("inside Mythread's run()");
classLocking();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static synchronized void classLocking() throws InterruptedException{
System.out.println("inside Mythread.classLocking()");
String threadName = Thread.currentThread().getName();
System.out.println("inside MyThread.classLocking() : CurrrentThreadName : "+ threadName);
/*
* outer class locking
*/
synchronized (Lock.class) {
System.out.println("I got lock on Lock.class definition");
Lock.STOP = false;
/*
* Outer class lock is not released. Lock on MyThread.class instance is released.
*/
MyThread.class.wait();
}
}
}
You are correct that it doesn't release the other lock. As for why, it's because it isn't safe to do so. If it was safe to release the outer lock during the call to the inner function, why would the inner function be called with the other lock held at all?
Having a function release a lock it didn't acquire behind the programmer's back would destroy the logic of synchronized functions.
Yes it is working correctly. A thread goes into waiting status releases the corresponding lock instead of all locks. Otherwise think about that: if things are like what you thought, then when a thread waits it loses all the acquired locks, which makes advanced sequential execution impossible.
The semantics of wait() is that the Thread invoking it notices that a lock was already acquired by another thread, gets suspended and waits to be notified by the thread holding the lock when the latter one releases it (and invokes notify). It doesn't mean that while waiting it releases all the locks acquired. You can see the wait's invocations as a number of barriers the thread meets on the way to acquiring all the locks it needs to accomplish an action.
Regarding the question "Why a thread doesn't release all the locks acquired when invoking wait" , I think the answer is that, doing so would make it more prone to starvation and it would also slow down the progress in a multithreaded application (All threads would give up all their locks when invoking the first wait and would have to start over when they acquire the lock they are currently waiting for. So, they would be in a permanent battle for locks.
Actually, in such a system, the only thread able to finish execution would be the one which manages to find all locks free when it needs them. This is unlikely to happen)
From JavaDoc of method 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.