提供线程阻塞原语的工具类
基本实现
LockSupport从名字看出是提供锁支持的,实现上定位是静态工具类
LockSupport.java1 2 3 4
| public class LockSupport { private LockSupport() {} }
|
底层基于UNSAFE实现,操控对象是线程
LockSupport.java1 2 3 4 5 6 7 8 9 10 11 12 13
| static { try { UNSAFE = sun.misc.Unsafe.getUnsafe(); Class<?> tk = Thread.class; parkBlockerOffset = UNSAFE.objectFieldOffset(tk.getDeclaredField("parkBlocker")); SEED = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomSeed")); PROBE = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomProbe")); SECONDARY = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomSecondarySeed")); } catch (Exception ex) { throw new Error(ex); } }
|
基本操作是park,阻止当前线程
参与调度,符合停车语义,提供定时和非定时操作
LockSupport.java1 2 3 4 5 6 7 8 9 10 11 12
| public static void park() { UNSAFE.park(false, 0L); }
public static void parkNanos(long nanos) { if (nanos > 0) UNSAFE.park(false, nanos); }
public static void parkUntil(long deadline) { UNSAFE.park(true, deadline); }
|
还可以在park时传入一个blocker对象,会设置到线程类中
对象可以取出,监控诊断工具可以通过对象提供更多信息,比如在dump中观察到,唤醒后会清空blocker对象
LockSupport.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public static Object getBlocker(Thread t) { if (t == null) throw new NullPointerException(); return UNSAFE.getObjectVolatile(t, parkBlockerOffset); } public static void park(Object blocker) { Thread t = Thread.currentThread(); setBlocker(t, blocker); UNSAFE.park(false, 0L); setBlocker(t, null); } public static void parkNanos(Object blocker, long nanos) { if (nanos > 0) { Thread t = Thread.currentThread(); setBlocker(t, blocker); UNSAFE.park(false, nanos); setBlocker(t, null); } } public static void parkUntil(Object blocker, long deadline) { Thread t = Thread.currentThread(); setBlocker(t, blocker); UNSAFE.park(true, deadline); setBlocker(t, null); }
|
解除方法只有一个,其他线程传入目标线程对目标进行唤醒
LockSupport.java1 2 3 4
| public static void unpark(Thread thread) { if (thread != null) UNSAFE.unpark(thread); }
|
park可能自己解除,比如遇到中断或者根本没有原因,需要在循环条件检测下使用
遇到中断也不会抛异常,只会解除,中断由线程自行检查
Sample1 2 3 4
| while (!canProceed()) { LockSupport.park(this); }
|
使用案例
文档自带例程,线程执行队列
Sample1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class FIFOMutex { private final AtomicBoolean locked = new AtomicBoolean(false); private final Queue<Thread> waiters = new ConcurrentLinkedQueue<Thread>();
public void lock() { boolean wasInterrupted = false; Thread current = Thread.currentThread(); waiters.add(current);
while (waiters.peek() != current || !locked.compareAndSet(false, true)) { LockSupport.park(this); if (Thread.interrupted()) wasInterrupted = true; }
waiters.remove(); if (wasInterrupted) current.interrupt(); }
public void unlock() { locked.set(false); LockSupport.unpark(waiters.peek()); } }
|
对比其他机制
LockSupport不涉及锁,单纯的让线程等待,是否放锁由外部逻辑,比如Condition.await
与WaitNotify,Condition比较
- Wait-Notify机制让线程等待在对象锁monitor上
- Condition机制让线程等待在显式锁上,底层基于LockSupport
与Thread.sleep比较
- Thread.sleep是定时自唤醒场景,必须传入时间
- LockSupport更加灵活,可以长期等待,可以主动唤醒