LockSupport通过unsafe提供阻塞和唤醒线程的方法,AQS和其他的lock都会使用到这个基础类。
private LockSupport() {} // Cannot be instantiated. private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long parkBlockerOffset; static { try { parkBlockerOffset = unsafe.objectFieldOffset (java.lang.Thread.class.getDeclaredField("parkBlocker")); } catch (Exception ex) { throw new Error(ex); } }
private static void setBlocker(Thread t, Object arg) { // Even though volatile, hotspot doesn't need a write barrier here. unsafe.putObject(t, parkBlockerOffset, arg); } public static Object getBlocker(Thread t) { if (t == null) throw new NullPointerException(); return unsafe.getObjectVolatile(t, parkBlockerOffset); }
考虑下面几种情况是为什么:
1.unpark->park,unpark释放一个许可,park直接返回,不阻塞;
2.unpark->park->park,unpark释放一个许可,2次park阻塞;
3.park->unpark->unpark,park阻塞后多次unpark,unpark修改_counter为1,多次调用也无所谓,为什么单独提出这个,是因为在AQS共享模式下,获取锁后,需要通知所有等待锁的线程,会从阻塞队列中删除/唤醒头结点使用for循环,我感觉有可能多次unpark操作(个人想法,不一定完全正确,谁了解的可以解释下)。
如果使用wait/notify来实现同步,notify在wait之前执行,wait会一直阻塞,就会出问题了。
带blocker参数和不带blocker参数:
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); } 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); }
1.有其他线程调用了本线程的unpark操作;
2.其他线程中断了本线程
3.The call spuriously (that is, for no reason) returns.
除了上面3种情况,底层Unsafe的public native void park(boolean flag, long l);下面情况也会唤醒:
1.flag为true,传入的dealline到了
2.flag为false,传入的park时间time到了
unpark操作唤醒后,线程调度就由各个平台自己控制:
<span style="font-size:18px;">public static void unpark(Thread thread) { if (thread != null) unsafe.unpark(thread); }</span>
参考:
http://blog.csdn.net/hengyunabc/article/details/28126139
http://www.360doc.com/content/14/0812/22/1073512_401408738.shtml