Key Insights
### Bare-Metal Thread Blocking
Ever wondered how Java tames threads under the hood? LockSupport.park() is the primitive that puts your thread to sleep until another thread deems it time to wake up—or until an interrupt barges in. It’s the atom in your synchronization molecule.
### Single-Permit Model
Think of permits as one-use bus tickets: unpark(thread) hands you a ticket (if you don’t already have one). park() consumes it to board or stalls you until one shows up. No more, no less—no ticket banking, no freebies.
### Diagnostic Blockers
Pass a blocker object to park(Object) and debuggers finally tell you why a thread is parked. It’s like adding sticky notes to your code, except these notes show up in jstack dumps.
## Common Pitfalls & Best Practices
### Permit Loss & Logic Traps
Banked wakeups? Nope. Fire unpark() twice before park()? You still owe your thread one wakeup. Always wrap park() in a while (!condition) loop to handle spurious wakeups and missing permits.
### Interrupts & Spurious Wakeups
Interruption isn’t a bug—park() returns immediately if interrupted. Spurious wakeups? Real. Double-check state in loops and handle interrupts properly to avoid 2 AM debugging sessions.
## When to Reach for Park/Unpark
Custom FIFO locks, high-performance synchronizers, and state machines love park/unpark. But for everyday locks, stick to ReentrantLock or synchronized blocks and save yourself the edge-case circus.
## Example: Simple FIFO Mutex
“`java
public void lock() {
Thread current = Thread.currentThread();
waiters.add(current);
while (waiters.peek() != current || !locked.compareAndSet(false, true)) {
LockSupport.park(this);
}
waiters.remove();
}
public void unlock() {
locked.set(false);
LockSupport.unpark(waiters.peek());
}
Build your queue, call `park()` on each node, and `unpark()` in order. Voilà—strict ordering without legacy bugs.
Could your last thread bug have been solved by park/unpark—or did it just park you in confusion?