ReentrantLock源码笔记

ReentrantLock

还不是很明白

参考

彤哥读源码

https://blog.csdn.net/u010805617/article/details/87260475

简介

ReentrantLock是Java SE 5新增的jdk层面实现可重入锁的功能, 提供了与synchronized类似的同步功能,只是在使用时需要显示的获取和释放锁。虽然缺少了隐私获取和释放锁的便捷性,但是缺拥有了锁获取和释放的可操作性、可中断的获取锁以及超时获取锁等多种synchronized关键字不具备的同步特性。同时也提供了获取和释放锁的灵活性。

公平锁和非公平锁

ReentrantLock提供了两种锁特性:公平锁和非公平锁,公平锁和非公平锁的区别是:
如果在绝对时间上,先对锁进行获取的请求一定先被满足,那么这个锁是公平的,反之,是不公平的。公平的获取锁,也就是等待时间最长的线程最优先获取锁,也可以说锁获取是顺序的。ReentrantLock提供了一个构造函数,能够控制锁是否是公平的。
事实上,公平的锁机制往往没有非公平的效率高,但是,并不是任何场景都是TPS作为唯一的指标,公平锁能够减少“饥饿”发生的概率,等待越久的请求越是能够到优先满足。

源码实现

 /** 
  * lock锁的同步控制,子类有公平和非公平两个版本。
  * 该抽象锁同步器主要提供了尝试获取(非公平实现)和尝试释放锁等功能
  **/
abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;
		// 获取锁,由子类实现
        abstract void lock();
		// 执行非公平的尝试获取锁操作。
        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            // 如果锁没有被占用,则尝试获取锁
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            // 通过判断当前线程是否为获取锁的线程来决定获取操作是否成功,如果是获取锁的线程
            // 再次请求,则将同步状态值进行增加并返回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;
        }
		// 如果该锁被获取了n次,那么前(n-1)次tryRelease(int releases)方法必须返回false,而只有		   
		// 同步状态完全释放了,才能返回true。可以看到,该方法将同步状态是否为0作为最终释放
	    // 的条件,当同步状态为0时,将占有线程设置为null,并返回true,表示释放成功。
        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);
            }
            setState(c);
            return free;
        }
		// 判断是否当前线程独占锁
        protected final boolean isHeldExclusively() {
            return getExclusiveOwnerThread() == Thread.currentThread();
        }
	
        final ConditionObject newCondition() {
            return new ConditionObject();
        }

        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }

        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;
        }

        final boolean isLocked() {
            return getState() != 0;
        }

        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // reset to unlocked state
        }
    }

公平锁

   /** 
    * 继承Sync, 并实现公平锁
    **/
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

		// 阻塞获取锁
        final void lock() {
            acquire(1);
        }
		// 尝试获取锁(公平策略),不能保证获取,除非递归调用或没有其他的线程等待获取锁
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            // 没有前驱,且设置锁标志位成功,获取锁成功
            if (c == 0) {
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    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;
        }
    }

非公平锁

    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;
		// 阻塞获取锁, 当前线程优先去获取锁,获取失败在通过队列的方式获取
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }
		// 非公平的方式尝试获取锁
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值