ReentrantLock分析

重入锁

    支持公平锁与非公平锁,在构造函数中体现,默认是非公平锁。

 /**
     * Creates an instance of {@code ReentrantLock}.
     * This is equivalent to using {@code ReentrantLock(false)}.
     */
    public ReentrantLock() {
        sync = new NonfairSync();
    }
 /**
     * Creates an instance of {@code ReentrantLock} with the
     * given fairness policy.
     *
     * @param fair {@code true} if this lock should use a fair ordering policy
     */
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
重入锁可以实现任意线程在获取到锁之后能够再次获取到锁,而且不会被阻塞,需要解决两个问题:

  (1)线程再次获取锁

        锁需要去识别获取所得线程是否为当前占据锁的线程,如果是,则再次获取成功,如果不是,则获取失败。

  (2)锁的最终释放

        所在每次成功获取锁之后,获取次数自增,每次释放锁时,次数自减,当次数为0时,才算最终成功释放锁。而在前面释放过程都返回false。

ReentrantLock是通过组合自定义同步器来实现所的获取与释放过程。以下是非公平性获取锁的JDK源码:

 /**
         * Performs non-fair tryLock.  tryAcquire is implemented in
         * subclasses, but both need nonfair try for trylock method.
         */
        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {   //如果是第一次获取该锁,则通过CAS操作后获取成功。
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {   //如果当前线程是占据锁的线程,
                int nextc = c + acquires;        //同步状态值自增
 if (nextc < 0) // overflow
	        throw new Error("Maximum lock count exceeded"); 
                setState(nextc); //设置当前同步状态值的次数
                return true;
            }
            return false;
      }

成功获取锁的线程再次获取锁,知识增加了同步状态值。以下是释放同步状态时减少同步状态值:
protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())   //如果当前线程没有占据锁,则抛出异常
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {    // 最终释放锁的判断条件
                free = true;
                setExclusiveOwnerThread(null);   // 将当前占据锁的线程设置为null
            }
            setState(c);
            return free;    //如果该锁被获得n次,那么在前n-1次释放时均返回false,最后一次返回true。
        }
 公平锁相比于非公平锁,其开销较小,非公平锁线程间切换次数少。公平锁保证了FIFO原则,代价是进行了大量的线程切换,非公平锁可能造成线程“饥饿”,但极少的线程切换保证了更大的吞吐量。



而对于公平锁,那么所得获取按照FIFO顺序,源码如下:
/**
         * Fair version of tryAcquire.  Don't grant access unless
         * recursive call or no waiters or is first.
         */
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {    //hasQueuedPredecessors()判断当前节点是否有前驱节点,如果有返回true,
                    setExclusiveOwnerThread(current);     //表示有现成比当前线程更早请求获取锁,则该线程不能获取锁,需要等待前驱节点获取锁后才能获取锁。

                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值