LockSupport

java编程之美 学习笔记

LockSupport

LockSupport是用来创建锁和其他同步类的基本线程阻塞原语 ,此类以及每个使用它的线程与一个许可关联。它的主要作用是挂起和唤醒线程,内部是使用Unsafe类实现的.

demo例

park()
如果调用park方法的线程已经拿到了LockSupport关联的许可证,则调用LockSupport.park()会立即返回,否则会阻塞。

public static void main(String[] args) throws InterruptedException {
		Thread thread = new Thread(() -> {
			System.out.println("begin park!");
			LockSupport.park();
			System.out.println("end park!");
		});
		
		thread.start(); 
	}

最终程序只会打印begin park,且一直阻塞在这里。
在这里插入图片描述

  • 仅在其他线程调用unpark(thread)方法将当前线程作为参数,阻塞的线程会返回。
  • 或调用阻塞线程的interrupt()方法设置中断标识,阻塞线程也会返回。因park()阻塞的线程被其他线程中断时不会抛出InterruptedException

unpark

	public static void main(String[] args) throws InterruptedException {
		Thread thread = new Thread(() -> {
			System.out.println("begin park!");
			LockSupport.park();
			System.out.println("end park!");
		});

		thread.start();
		TimeUnit.SECONDS.sleep(10);
		System.out.println("---------------------afeter sleeep 10s.");
		LockSupport.unpark(thread);
/*		thread.interrupt();*/
	}

打印结果:
在这里插入图片描述

源码分析

Unsafe回顾

  /**
     * 阻塞当前线程
     * @param var1 : isAbsolute,表示是否为绝对时间
     * @param var2 : time
     * 
     * 当isAbsolute=false时,即不是绝对时间,即为相对时间,此时时间单位为nanos
     * 	- time = 0,表示一直阻塞 
     *  - time > 0,表示time时间段后,阻塞线程会被唤醒
     * 
     * 当isAbsolute=true时,即是绝对时间:
     *  - time > 0, 这里time是个绝对时间,是将某个时间转换计算为ms后的值,表示当前则色线程到某一个时间点后会被唤醒
     */
	public native void park(boolean var1, long var2);

	
	/**
	 * 唤醒调用 park 后阻塞的线程。
	 * @param var1 : Thread obj
	 */
    public native void unpark(Object var1);

LockSupport

public class LockSupport {
 	private LockSupport() {}

    private static void setBlocker(Thread t, Object arg) {
        UNSAFE.putObject(t, parkBlockerOffset, arg);
    }

    //通过诊断工具观察线程阻塞原因
    public static Object getBlocker(Thread t) {
        if (t == null)
            throw new NullPointerException();
        return UNSAFE.getObjectVolatile(t, parkBlockerOffset);
    }

    //无参的park() 
    public static void park() {
    	//无限期待阻塞线程
        UNSAFE.park(false, 0L);
    }

    public static void parkNanos(long nanos) {
        if (nanos > 0)
        	//阻塞线程 nanos;
            UNSAFE.park(false, nanos);
    }


  	public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        //设置线程t的parkBlocker
        setBlocker(t, blocker);
        
        //挂起线程	
        UNSAFE.park(false, 0L);

        //线程被激活后,清除blocker变量,因为一般线程在阻塞时才分析原因
        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);
        }
    }


    /**
     * @param blocker  
     * @param deadline deadline单位为毫秒,epochtime
     */
    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 parkUntil(long deadline) {
        UNSAFE.park(true, deadline);
    }

    //
    public static void unpark(Thread thread) {
        if (thread != null)
            UNSAFE.unpark(thread);
    }

}

JDK推荐带有blocker参数的park方法,且blocker设置为this.

FIFOMutex
以下是一个先进先出 (first-in-first-out) 非重入锁类的框架.

public 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);

		// 当当前线程不是队首时, 或者 locked为true时,即锁被其他线程获取了;
		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());
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值