java-并发-源码-LockSupport
LockSupport.park()实现分析
一.成员及方法
    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); }
    }
可以看出parkBlocker是unsafe的成员
// 返回提供给最近一次尚未解除阻塞的 park 方法调用的 blocker 对象,如果该调用不受阻塞,则返回 null。
static Object getBlocker(Thread t)
// 为了线程调度,禁用当前线程,除非许可可用。
static void park()
// 为了线程调度,在许可可用之前禁用当前线程。
static void park(Object blocker)
// 为了线程调度禁用当前线程,最多等待指定的等待时间,除非许可可用。
static void parkNanos(long nanos)
// 为了线程调度,在许可可用前禁用当前线程,并最多等待指定的等待时间。
static void parkNanos(Object blocker, long nanos)
// 为了线程调度,在指定的时限前禁用当前线程,除非许可可用。
static void parkUntil(long deadline)
// 为了线程调度,在指定的时限前禁用当前线程,除非许可可用。
static void parkUntil(Object blocker, long deadline)
// 如果给定线程的许可尚不可用,则使其可用。
static void unpark(Thread thread)
二. park与unpark
park
  public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(false, 0L);
        setBlocker(t, null);
    }
传入的Object对象,用setBlocker创建为一个blocker
    private static void setBlocker(Thread t, Object arg) {
        UNSAFE.putObject(t, parkBlockerOffset, arg);
    }
putObject方法如下:
public native void putObject(Object o, long offset, Object x);
把线程作为对象传入了Unsafe,unsafe就可以操作这个线程
把blocker写入unsafe
然后调用unsafe的park方法
unsafe.park会block当前的线程,只有如下方法可以唤醒:unpark,线程被interrupted,时间超时
调用unpark方法必须保证该线程没有被销毁
unpark
   public static void unpark(Thread thread) {
        if (thread != null)
            UNSAFE.unpark(thread);
    }
LockSupport的park方式入一个对象,而synchronized阻塞必须调用synchronized
park和unpark方法,直接作用于传入的线程
三. 使用例子
例子如下:
public class LockSupportTest1 {
    private static Thread mainThread;
    public static void main(String[] args) {
        ThreadA ta = new ThreadA("ta");
        mainThread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName()+" start ta");
        ta.start();
        System.out.println(Thread.currentThread().getName()+" block");
        LockSupport.park(mainThread);
        System.out.println(Thread.currentThread().getName()+" continue");
    }
    static class ThreadA extends Thread{
        public ThreadA(String name) {
            super(name);
        }
        public void run() {
            System.out.println(Thread.currentThread().getName()+" wakup others");
            LockSupport.unpark(mainThread);
        }
    }
}
 
                    
                
 
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号