Unsafe.park vs Object.wait

Most efficient wait is LockSupport.park/unpark, which doesn't require nasty (direct) usage of Unsafe, and doesn't pay to resynchronize your thread's local cache of memory.

This point is important; the less work you do, the more efficient. By not synchronizing on anything, you don't pay to have your thread check with main memory for updates from other threads.

In most cases, this is NOT what you want. In most cases, you want your thread to see all updates that happened "before now", which is why you should use Object.wait() and .notify(), as you must synchronize memory state to use them.

LockSupport allows you to safely park a thread for a given time, and so long as no other thread tries to unpark you, it will wait for that long (barring spurious wake ups). If you need to wait for a specific amount of time, you need to recheck the deadline and loop back into park() until that time has actually elapsed.

You can use it to "sleep" efficiently, without another thread to have to wake you up via LockSupport.parkNanos or .parkUntil (for millis; both methods just call Unsafe for you).

If you do want other threads to wake you up, chances are high that you need memory synchronization, and should not use park (unless carefully orchestrating volatile fields without race conditions is your thing).

Good luck, and happy coding!


You're not supposed to use either of these methods if you're an application programmer.

They are both too low level, easy to screw up and not meant to be used outside libraries.

Why not try to use a higher level construct like java.util.concurrent.locks ?

To answer your question. park(...) works directly on the thread. It takes the thread as a parameter and puts it to sleep until unpark is called on the thread, unless unpark has already been called.

It's supposed to be faster than Object.wait(), which operates on the monitor abstraction if you know which thread you need to block/unblock.

Btw unpark is not really that Unsafe if used from inside Java:

public native void unpark(Object thread)

Unblock the given thread blocked on park, or, if it is not blocked, cause the subsequent call to park not to block. Note: this operation is "unsafe" solely because the caller must somehow ensure that the thread has not been destroyed. Nothing special is usually required to ensure this when called from Java (in which there will ordinarily be a live reference to the thread) but this is not nearly-automatically so when calling from native code.


LockSupport.park/unpark has better performance, but it's too low level API.

Besides, they have some different operations maybe you should notice:

    Object lockObject = new Object();
    Runnable task1 = () -> {
        synchronized (lockObject) {
            System.out.println("thread 1 blocked");
            try {
                lockObject.wait();
                System.out.println("thread 1 resumed");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    };
    Thread thread1 = new Thread(task1);
    thread1.start();

    Runnable task2 = () -> {
        System.out.println("thread 2 running ");
        synchronized (lockObject) {
            System.out.println("thread 2 get lock");
            lockObject.notify();
        }
    };
    Thread thread2 = new Thread(task2);
    thread2.start();

In this case, thread2 can get lock and notify the thread1 to resumed, because lockObject.wait(); will release the lock.

    Object lockObject = new Object();
    Runnable task1 = () -> {
        synchronized (lockObject) {
            System.out.println("thread 1 blocked");
            LockSupport.park();
            System.out.println("thread 1 resumed");

        }
    };
    Thread thread1 = new Thread(task1);
    thread1.start();

    Runnable task2 = () -> {
        System.out.println("thread 2 running ");
        synchronized (lockObject) {
            System.out.println("thread 2 get lock");
            LockSupport.unpark(thread1);
        }
    };
    Thread thread2 = new Thread(task2);
    thread2.start();

However, if you use LockSupport.park/unpark like this, it will cause dead lock. because thread1 won't release the lock by using LockSupport.park. therefore, thread1 can't resumed.

So be careful, they have different behaviors besides blocking the thread. And in fact, there are some Class we can use it conveniently to coordinate in multi-thread environment, such as CountDownLatch, Semaphore, ReentrantLock