First, a really dumb question, I was just wondering what the waiting \'parking\' means ? Is the thread waiting to be parked or is it just been parked and therefore is in wai
As per the java Thread State Documentation, A thread can go to WAITING state for three reasons:
When you call a park method on a Thread, it disables the thread for thread scheduling purposes unless the permit is available. You can call unpark method to make available the permit for the given thread, if it was not already available.
So, when your Thread is in WAITING mode by LockSupport.park, it will show you as WAITING (parking).
Please make note that, you can call park on current Thread only. This is very helpful mechanism to implement Producer-Consumer Design Pattern.
Permit means a permission to continue execution. Parking means suspending execution until permit is available.
Unlike Semaphore's permits, permits of LockSupport
are associated with threads (i.e. permit is given to a particular thread) and doesn't accumulate (i.e. there can be only one permit per thread, when thread consumes the permit, it disappears).
You can give permit to a thread by calling unpark()
. A thread can suspend its execution until permit is available (or thread is interrupted, or timeout expired, etc) by calling park()
. When permit is available, the parked thread consumes it and exits a park()
method.
The part that made me revisit this question that I could not get around while reading the documentation, was:
If the permit is available then it is consumed and the call returns immediately...
So when the permit is "available", who and how makes it available, so that it could get consumed immediately? This was somehow trivial to find out:
public static void main(String[] args) {
Thread parkingThread = new Thread(() -> {
System.out.println("Will go to sleep...");
sleepTwoSeconds();
System.out.println("Parking...");
// this call will return immediately since we have called LockSupport::unpark
// before this method is getting called, making the permit available
LockSupport.park();
System.out.println("After parking...");
});
parkingThread.start();
// hopefully this 1 second is enough for "parkingThread" to start
// _before_ we call un-park
sleepOneSecond();
System.out.println("Un-parking...");
// making the permit available while the thread is running and has not yet
// taken this permit, thus "LockSupport.park" will return immediately
LockSupport.unpark(parkingThread);
}
private static void sleepTwoSeconds() {
try {
Thread.sleep(1000 * 2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static void sleepOneSecond() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
The code speaks for itself, the thread
is running but not yet called LockSupport.park
, while some other thread calls LockSupport.unpark
on it - thus making the permit available. After that we call LockSupport.park
and that returns immediately since the permit is available.
Once you think about it, this is a bit dangerous, if you expose your threads to some code you do not control and that code calls LockSupport.unpark
while you park
after that - it might not work.
From the class description (at the top of the LockSupport javadoc) where it describes the permit:
This class associates with each thread that uses it, a permit (in the sense of the Semaphore class). A call to park will return immediately if the permit is available, consuming [the permit] in the process; otherwise [the call to park] may block. A call to unpark makes the permit available, if it was not already available. (Unlike with Semaphores though, permits do not accumulate. There is at most one.)
(I expanded the [text] to make it easier to read for non-English speakers.)
Hopefully somebody with a deeper understanding can elaborate on this. See axtavt's answer.
As a final note, a final quote from the javadoc:
These methods are designed to be used as tools for creating higher-level synchronization utilities, and are not in themselves useful for most concurrency control applications.
As i understand it, the "permit" is just an object that represent if a Thread can be "unparked" or not. And this is checked by the Thread itself (or de JRE when you try to park a Thread) The "is consumed" thing, i understand that the permit dissapears and the Thread is not dissabled.
I think you should learn a little bit more about multithreading.. Think of it as a dispenser with Objects called "permit". You tell to a Thread to park, and the Thread check the dispenser, if there is a "permit", the Thread take it and leaves(without park). If there is no "permit" in the dispenser the Thread is parked until a "permit" is avaliable (and you can put a "permit" in the dispenser with unpark
.
As for the CPU/memory usage, i think that depends of the OS, etc...