读ReentrantLock 源码笔记

 

ReentrantLock有以下几个特性。 基本的获取锁操作,基本的释放锁操作,可轮询的锁获取操作,可中断的获取锁操作,定时获取锁操作,使用公平队列。

首先ReentrantLock的实现主要是依赖于 AbstractQueuedSynchronizer。AbstractQueuedSynchronizer它维护一个状态信息单一的整数 state。state在此用来表示拥有锁的线程请求获取锁的次数。 state==0表示锁为可获取状态

基本的获取锁操作:lock()方法:
public void lock() {
sync.lock();
}
sync为ReentrantLock静态内部类Sync的一个引用。
无参数的构造函数默认sync指向一个NonfairSync().(不公平队列)。Sync扩展了AbstractQueuedSynchronizer.而NonfairSync扩展了Sync.
NonfairSync中lock()方法的实现如下:
       final void lock() {
            if (compareAndSetState(0, 1))//AbstractQueuedSynchronizer的方法(原子操作),如果当前的state的值为0则把state的值设为1
                setExclusiveOwnerThread(Thread.currentThread());//设置当前锁的有占有者为当前线程
            else
                acquire(1);//如果是拥有锁的线程请求state++,否则当前线程阻塞,并且把线程存储到阻塞队列中。(AbstractQueuedSynchronizer中使用链表来维护的线程阻塞队列)
        }
 
 
可轮询的锁获取操作:具体的实现为:
        final boolean nonfairTryAcquire(int acquires) {//此处acquirs为1
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {//如果state为0证明锁可获取
                if (compareAndSetState(0, acquires)) {//原子操作,如果当前的state为0,则把state的值设置为1.
                    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);//设置state为占有锁线程请求锁的次数
                return true;
            }
            return false;
        }
 
基本的释放锁操作:

 

        protected final boolean tryRelease(int releases) {//此处releases值为1
            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;
        }
 
使用公平队列:公平队列的获取锁操作和非公平队列获取锁操作的主要区别在于多了一个判断isFirst(current)判断当前的线程是否是阻塞队列中第一个元素。以此来实现公平队列。
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (isFirst(current) && //与非公平队列的主要不同点
                        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;
        }
 
ReentrantLock的实现主要依赖于AbstractQueueSynchronizer,但是ReentrantLock不是扩展AQS而是使用委托,使用静态内部类。这样有个好处在于保持类的整洁性,只暴露需要对外公开的方法。如果扩展AQS的话就会暴露过多的方法,调用者容易误调用这些方法。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值