If you are familiar with thread dump or at least looked at it couple of times, probably you would have noticed WAITING & WAITING (parking) states. So what’s the difference?
In Java, we have Objects.wait() and Unsafe.park() methods. Both of them will suspend the running thread & put it in waiting state. But these two methods work on different principles. Objects.wait() results in WAITING state whereas Unsafe.park() method results in WAITING (parking) state.
Object.wait() method works on monitor based synchronization. So, that works well with “happens-before” relationship in Java. To bring back a waiting thread in runnable state, we will use Object.notify() method on the same monitor object. When the thread comes back to runnable state, it will surely get updated values of the variables shared across multiple threads. JVM will make sure that thread state is synchronized with main memory, but that is also an additional overhead.
Unsafe.park() method takes the thread as an argument. To move back a parked thread to runnable state, we need to call Unsafe.unpark() method on the same thread. It works on permit basis. When Unsafe.unpark() is called, it will unblock the thread in case it is already parked. Otherwise it will make sure that the next park() call on the thread is unblocked immediately. Its performance should be better as no synchronization is required with main memory. That’s why thread pool in general (for example ExecutorService) use park method while waiting for tasks from the blocking queue.
As you can see, these use cases are different. If you have object state that is shared across multiple threads & you want to make sure one thread should wait for other thread before proceeding with the update, then you should go ahead with wait() and notify() methods. As an application developer, mostly you won’t have to use park() method. It’s a pretty low level API.