源码解析:ReenTrantLock(重入锁)/公平性锁/非公平性锁/AQS是怎样实现的?

一 、ReenTrantLock(重入锁)

  1. 继承关系
    ReenTrantLock实现Lock和序列化接口
    在这里插入图片描述
    Lock接口提供的方法有:
    void lock();//加锁操作
    void lockInterruptibly() throws InterruptedException;//可中断加锁
    boolean tryLock();//尝试性的进行加锁
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;//在有限时间内进行尝试性加锁
    void unlock();//释放锁
    Condition newCondition(); //通信类
    在这里插入图片描述
    三个内部类:Sync、NonfairSync、FairSync
    在这里插入图片描述
    1) 抽象类Sync继承了 AbstractQueuedSynchronizer(AQS)类
    在这里插入图片描述
    2) NonfairSync继承 Sync抽象类
    在这里插入图片描述
    3) FairSync继承 Sync抽象类
    在这里插入图片描述
  2. 构造函数
ReentrantLock() {    //无参构造,创建一个 ReentrantLock 的实例。默认非公平性锁
     sync = new NonfairSync();
 	}
    
ReentrantLock(boolean fair){  //创建一个具有给定公平策略的 ReentrantLock,默认false采用非公平性锁
  sync = fair ? new FairSync() : new NonfairSync();
   }
   
  1. 基本属性
 private final Sync sync;  //抽象sync类型的sync
  1. 常用方法
方法作用
int getHoldCount()查询当前线程获取此锁的次数。
isHeldByCurrentThread()查询当前线程是否获取此锁
final Thread getOwner()返回目前获取此锁的线程,
boolean hasQueuedThreads()查询是否有线程正在等待获取锁
boolean hasQueuedThread()判断传进来的线程是否处于阻塞队列中
boolean hasWaiters(Condition condition)判断当前condition的实例是否处于wait状态
void lockInterruptibly()如果当前线程未被中断,则获取锁
boolean tryLock()仅在调用时锁未被另一个线程保持的情况下,才获取该锁
void unlock()试图释放锁
Condition newCondition()返回用来与此 Lock 实例一起使用的 Condition 实例。
  1. 重入锁的实现
    ReentrantLock锁的实现中使用到AQS(AbstractQueuedSynchronizer)类
    线程获取锁会修改state值,当前线程每获取一次锁会对state做+1操作,未获取锁则放入AQS提供的队列中,线程释放锁会对state-1,当state=0时才真正释放锁

  2. 三大主要的内部类
    ==①Sync:继承AbstractQueuedSynchronizer ==

 abstract static class Sync extends AbstractQueuedSynchronizer {
        abstract void lock();
  final boolean nonfairTryAcquire(int acquires) {
			 //获取当前线程
            final Thread current = Thread.currentThread();
			//获取当前锁的状态:0空闲,>0占用,<0溢出
            int c = getState();
            if (c == 0) {//空闲
				//CAS获取锁,获取成功则将state置为1,并且将当前线程记录下来,直接返回
                if (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); //若没到达上限,则直接更新state,直接返回
                return true;
            }
            return false; //若当前获取锁的线程不是当前的线程,返回false
        }

//释放锁操作
protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
			//如果当前获取锁的线程不是当前的线程,抛出异常
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
			//当state减为1的时候才真正释放锁,将持有锁的线程置为null
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);//把当前获取锁的线程置为null
            }
            setState(c);
            return free;
        }		
//序列化需要重写的方法!
private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); 
        }
    }

②NonfairSync(非公平性锁):继承 Sync抽象类
两次抢锁
1.第一次通过CAS强制抢锁,
2.强制抢锁失败则第二次尝试性抢锁,
a.首先判断当前锁是否空闲(state=0),是则直接通过CAS获取锁,获取成功则修改state且将当前线程写入AQS中。
b.在锁占用的情况下,占用锁的线程为当前线程则直接修改state,成功返回。
c.以上都不满足,失败返回

 static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        final void lock() {
        //先通过CAS强制获取锁
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else  //获取失败,尝试抢锁
                acquire(1);  //调用AQS的acquire方法
        }
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }
   //AQS的 acquire()方法
  public final void acquire(int arg) {
		//如果tryAcquire为false直接放入队列中
        if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

③fairSync(公平性锁):继承Sync抽象类
一次抢锁
1.尝试性获取锁,
如果锁空闲,判断当前线程是否满足条件(判断AQS队列为空或者当前线程是否处于队列的队头),
修改state,将当前线程记录到AQS中,成功返回)
如果锁被占用,并且是当前线程占有锁,修改state,成功返回
如果都不满足,则失败返回
2.如果未获取到锁,则将线程加入AQS中的队列

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) {
            //!hasQueuedPredecessors():当前队列为空并且当前线程为队列中处于头结点的线程
            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;
        }
    }
//AQS的 hasQueuedPredecessors()方法
 public final boolean hasQueuedPredecessors() {
        Node t = tail;
        Node h = head;
        Node s;
		//返回 队列不为空 && (队列中只有一个节点 || 当前线程不等于头结点存储的线程)
        return h != t &&((s = h.next) == null || s.thread != Thread.currentThread());
         }
  1. AbstractQueuedSynchronizer类
    这个类基于FIFO队列,没有获取到锁的线程放入队列中,可以用于构建锁或者其他相关同步装置的基础框架。该同步器(以下简称同步器)利用了一个int类型的state来表示状态:
    state=0表示锁是空闲状态
    state>0表示锁被占用
    state<0表示溢出

    FIFO队列中的元素Node就是保存着线程引用和线程状态的容器,
    每个线程对同步器的访问,都可以看做是队列中的一个节点Node。

    Node的主要包含以下成员变量:
    Node {
    int waitStatus;//节点的状态
    Node prev;//前驱节点
    Node next;//后继节点
    Node nextWaiter;//存储condition队列中的后继节点
    Thread thread;//入队列时的当前线程
    }

//节点的状态:
static final class Node {
        static final Node SHARED = new Node();
        
        static final Node EXCLUSIVE = null;

        static final int CANCELLED =  1; 
         //CANCELLED,值为1,表示当前的线程被取消;

        static final int SIGNAL    = -1; 
         //SIGNAL,值为-1,表示当前节点的后继节点包含的线程需要运行,也就是unpark;

        static final int CONDITION = -2; 
         //CONDITION,值为-2,表示当前节点在等待condition,也就是在condition队列中
   
        static final int PROPAGATE = -3;  
        //PROPAGATE,值为-3,表示当前场景下后续的acquireShared能够得以执行;值为0,表示当前节点在sync队列中,等待着获取锁。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值