LockSupport类
Posted wqff-biubiu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LockSupport类相关的知识,希望对你有一定的参考价值。
LockSupport类是个工具类,主要作用是挂起和唤醒线程,是创建锁与其他同步类的基础
LockSupport类与每个使用它的线程都会关联一个许可证,默认情况下调用LockSupport类的方法的线程是不持有许可证的。LockSupport是unsafe类park、unpark方法的封装使用。
一、构造方法与变量
private LockSupport() {} // Cannot be instantiated.工具类不能实例化 // Hotspot implementation via intrinsics API private static final sun.misc.Unsafe UNSAFE; private static final long parkBlockerOffset; private static final long SEED; private static final long PROBE; private static final long SECONDARY; 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); } }
二、方法
LockSupport的方法基本上是unsafe的简单封装,如下park(Object blocker)的源码。
blocker是阻塞时记录到线程内部的对象,在线程阻塞时,诊断工具可以获取对象进行分析,JDK推荐使用带参数blocker的park方法,将blocker设置为this,可打印线程堆栈排查问题时得知哪个类被阻塞了
public static void park(Object blocker) { Thread t = Thread.currentThread(); setBlocker(t, blocker);// UNSAFE.park(false, 0L); setBlocker(t, null);// }
三、例子及部分方法的说明
public class LockSupportTest { /** * LockSupport.park():阻塞线程 * 当前线程已拿到LockSupport关联的许可证时,立刻返回 * 否则阻塞挂起 */ @Test public void parkTest(){ System.out.println("begin park!"); LockSupport.park(); System.out.println("end park"); } /** * LockSupport.unpark():线程唤醒 * 参数线程如果没有持有thread与LockSupport的关联许可证,则让线程持有, * park()后unpark(thread)可以唤醒park()阻塞的thread--下面unparkTest2() * 若unpark后park(),--下面unparkTest() */ @Test public void unparkTest(){ System.out.println("begin park!"); LockSupport.unpark(Thread.currentThread()); LockSupport.park(); System.out.println("end park"); } @Test public void unparkTest2() throws InterruptedException { Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println("child thread begin park"); LockSupport.park(); System.out.println("child thread unpark"); } }); thread.start(); Thread.sleep(1000); System.out.println("main thread begin unpark"); LockSupport.unpark(thread); } /** * thread.interrupt()也可以引起park()的返回 * 所以park()阻塞后返回,不会告诉是何种原因返回,所以需要根据park()原因,检查条件是否满足 * 即是否符合条件后unpark还是被中断 * @throws InterruptedException */ @Test public void unparkTest3() throws InterruptedException { Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println("child thread begin park!"); while(!Thread.currentThread().isInterrupted()){ LockSupport.park(); } System.out.println("child thread unpark"); } }); thread.start(); Thread.sleep(1000); System.out.println("main thread begin unpark"); thread.interrupt(); } public void testPark(){ LockSupport.park(this); } /** * park(Object blocker),阻塞时,传入this,可检查哪个类阻塞 * 当线程唤醒后,会清除blocker,所以一般都是在线程阻塞时才分析原因blocker */ @Test public void parkTest1(){ LockSupportTest test = new LockSupportTest(); test.testPark(); } /** * parkNanos(long nanos),阻塞nanos纳秒 */ @Test public void parkNanosTest(){ System.out.println("begin park!"); LockSupport.parkNanos(2000000000);//ns System.out.println("end park"); } /** * parkUntil(long nanos),阻塞至deadline毫秒 */ @Test public void parkUntilTest(){ System.out.println("begin park!"); LockSupport.parkUntil(this, new Date().getTime() + 10000);//ms System.out.println("end park"); } }
FIFO锁
public class FIFOMutex { private final AtomicBoolean locked = new AtomicBoolean(false); private final Queue<Thread> waiters = new ConcurrentLinkedDeque<>(); 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类的主要内容,如果未能解决你的问题,请参考以下文章