ReentrantLock 超时锁2

本文需要前置知识,请参阅
ReentrantLock 解决锁分析 1

文章目录

例子

		
		ReentrantLock reentrantLock = new ReentrantLock(false);
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                reentrantLock.lock();
            }
        }).start();
        //保证子线程已经加锁
        TimeUnit.SECONDS.sleep(1);

        //,此时如果在1秒内没有获得锁那么会返回false
        boolean lockSucceed = reentrantLock.tryLock(1, TimeUnit.SECONDS);

        if (lockSucceed) {
            System.out.printf("lockSucceed");
        } else {
            System.out.printf("not lockSucceed");
        }

ReentrantLocktryLock提供超时锁机制,在指定时间获取锁成功返回true,反之false。

//ReentantLock.java
 public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }

不管公平锁还是非公平锁最终调回到AQS

//AbstractQueuedSynchronizer.java
 public final boolean tryAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        return tryAcquire(arg) ||
            doAcquireNanos(arg, nanosTimeout);
    }

doAcquireNanos其实和常规自旋加锁代码差不多。非超时自旋锁代码分析可以参考
自定义AQS

//AbstractQueuedSynchronizer.java
 private boolean doAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        //超时时间非法直接返回    
        if (nanosTimeout <= 0L)
            return false;
        //这个获取锁最大等候的时间点的时间戳,比如等到下午11点的时间戳(纳秒) 
        final long deadline = System.nanoTime() + nanosTimeout;
        //将当前线程添加到CLH队列尾部
        final Node node = addWaiter(Node.EXCLUSIVE);
        boolean failed = true;
        try {
            for (;;) {
            	//前节点
                final Node p = node.predecessor();
                //如果前节点是HEAD那么可以进行尝试获取锁
                if (p == head && tryAcquire(arg)) {
                	//获取成功
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return true;
                }
                //计算要休眠的时间
                nanosTimeout = deadline - System.nanoTime();
                //小于等于0,证明最终期望时间内没获得锁
                if (nanosTimeout <= 0L)
                    return false;
                 //shouldParkAfterFailedAcquire表示获取锁失败之后是否应该休眠
                 //,此函数具体参考博主链接。
                 // nanosTimeout > spinForTimeoutThreshold 如果休眠时间 很小
                 //那么还不如自旋,这样还可以提高整体响应速度。spinForTimeoutThreshold为1000L
                if (shouldParkAfterFailedAcquire(p, node) &&
                    nanosTimeout > spinForTimeoutThreshold)
                    //休眠指定时间后再次获取锁
                    LockSupport.parkNanos(this, nanosTimeout);
                if (Thread.interrupted())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页