In the realm of high-performance, low-level Java concurrency, the LockSupport
class stands out as a powerful tool. It allows developers to build advanced synchronization utilities using low-overhead mechanisms—namely, park()
and unpark()
.
Unlike traditional synchronization tools like synchronized
, wait()
, or Lock
, LockSupport
provides fine-grained control over thread parking (blocking) and unparking (waking), making it ideal for frameworks like ForkJoinPool
or custom lock implementations.
What is LockSupport?
LockSupport
is a utility class in java.util.concurrent.locks
that provides methods to block (park) and unblock (unpark) threads.
It’s used internally by many Java concurrency utilities and is designed to be more flexible and efficient than Object.wait()
/ notify()
.
public class LockSupport {
public static void park(); // Blocks current thread
public static void unpark(Thread t); // Unblocks the given thread
}
park() and unpark() – Core Mechanism
How park()
Works
- Parks (blocks) the current thread unless/until it's permitted to proceed.
- The permit is like a one-time token: once consumed, the thread blocks again until another token is granted.
How unpark(Thread t)
Works
- Grants a permit to the specified thread.
- If the thread is currently parked, it gets unblocked.
- If it's not parked, the next
park()
will not block (because the permit is already available).
Real-World Analogy
Imagine a toll gate (thread execution) that only opens when you show a token (permit).
park()
= wait at the gate for a token.unpark()
= someone gives you a token to move forward.
Tokens don’t stack. If you already have a token and someone gives another, it’s wasted.
Basic Example
public class ParkUnparkExample {
public static void main(String[] args) {
Thread t = new Thread(() -> {
System.out.println("Thread parking...");
LockSupport.park();
System.out.println("Thread resumed!");
});
t.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println("Unparking thread...");
LockSupport.unpark(t);
}
}
Advanced Use Case: Custom Blocking Queue
LockSupport
is often used to build lock-free or wait-free data structures:
class SimpleQueue {
private Node head, tail;
static class Node {
final Thread thread;
Node next;
Node(Thread thread) {
this.thread = thread;
}
}
public void enqueue() {
Node node = new Node(Thread.currentThread());
// add to queue
// ...
LockSupport.park(); // Wait until dequeued
}
public void dequeue() {
// remove from queue
Node node = /*...*/ null;
if (node != null) LockSupport.unpark(node.thread);
}
}
Thread Lifecycle and Visibility
LockSupport
operations are safe with respect to the Java Memory Model.- It doesn’t require explicit
synchronized
orvolatile
, but when mixed, ensure proper visibility rules are upheld.
Java Version Tracker
📌 What's New in Java Versions?
- Java 8:
LockSupport
used inForkJoinPool
,StampedLock
- Java 11+:
- No major changes but enhanced integration with concurrent structures
- Java 21:
- Structured concurrency uses underlying
LockSupport
strategies - Virtual threads built atop park/unpark-like suspension points
- Structured concurrency uses underlying
Best Practices
- Always pair
park()
with a correspondingunpark()
— but order doesn’t matter. - Use
LockSupport
in low-level utilities, not in everyday app code. - Avoid using in loops without timeout or interrupt handling.
Common Pitfalls
- Forgetting to unpark → thread stays blocked forever
- Calling
unpark()
multiple times → only 1 permit allowed - Using
park()
without timeout/interrupt check → possible deadlock
Comparison Table
Feature | park()/unpark() | wait()/notify() |
---|---|---|
Interrupt support | Yes | Yes |
Must own lock? | No | Yes |
Wake-up token queues? | No | Yes |
Lost notifications? | No | Yes |
Flexibility | High | Low |
FAQ
1. Why use LockSupport
instead of wait()/notify()
?
Because it’s more flexible, low-level, and doesn’t require monitor locks.
2. Can you call unpark()
before park()
?
Yes, the permit is stored and consumed by the next park()
.
3. What happens if park()
is called twice?
The first call consumes the permit. Second will block until another unpark()
.
4. Is it safe to use LockSupport
with threads from thread pools?
Yes, but be cautious about blocking threads in pools with limited capacity.
5. Is LockSupport
interruptible?
Yes, use parkNanos()
or check Thread.interrupted()
after park()
.
6. How does LockSupport relate to virtual threads?
Virtual threads rely on park/unpark
for suspension and resumption.
7. Can I use LockSupport for implementing custom locks?
Absolutely. Many advanced locks internally rely on it.
8. Does it use busy-wait or blocking?
It uses OS-level blocking, so it’s efficient.
9. What is the role of permits in LockSupport?
Each thread has at most one permit—acts like a binary semaphore.
10. Are there any alternatives to LockSupport?
Use it only when ReentrantLock
, synchronized
, or Condition
are not enough.
Conclusion and Key Takeaways
LockSupport
gives precise control over thread blocking/waking.- Great for building high-performance concurrent frameworks.
- But with power comes responsibility—misuse can cause subtle bugs.
- Understand how permits work and always design unblocking logic carefully.