ReentrantLock源码分析

栏目: 编程工具 · 发布时间: 5年前

内容简介:Reentrantlock是并发包中可重入的独占锁,只能有一个线程占有锁,锁的获取和释放是基于AQS(AbstractQueuedSynchronized)实现的, 有公平和不公平两种获取锁的实现方式。Reentranlock 中有一个内部抽象类Sync继承自AbstractQueuedSynchronized, 主要是它来实现锁获取和释放的功能,Sync 在ReentrantLock中有两种实现类:NonfairSync(非公平获取锁)、FairSync(公平获取锁), Reentrantlock支持Co

一、简介

Reentrantlock是并发包中可重入的独占锁,只能有一个线程占有锁,锁的获取和释放是基于AQS(AbstractQueuedSynchronized)实现的, 有公平和不公平两种获取锁的实现方式。Reentranlock 中有一个内部抽象类Sync继承自AbstractQueuedSynchronized, 主要是它来实现锁获取和释放的功能,Sync 在ReentrantLock中有两种实现类:NonfairSync(非公平获取锁)、FairSync(公平获取锁), Reentrantlock支持Condition,AQS中有同步队列和条件队列,不清楚的,可以看下另一篇AbstractQueuedSynchronized的源码分析。

还没写完,有空继续写

二、类关系

ReentrantLock源码分析

//独占锁的接口,以下方法在下面都会详细的介绍
public interface Lock {
    
    //加锁,不支持中断
    void lock();
    
    //加锁,支持中断,抛出中断异常
    void lockInterruptibly() throws InterruptedException;
    
    //尝试加锁,不支持中断
    boolean tryLock();
    
    //在超时时间内获取锁  
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    
    //解锁
    void unlock();
    
    //获取条件变量Condition 
    Condition newCondition();
}复制代码

三、属性

//Reentrantlock锁的获取和释放都是基于Sync,Sync 在ReentrantLock中有两种实现类:NonfairSync(非公平获取锁)、FairSync(公平获取锁),下面会详细介绍Sync
private final Sync sync;复制代码

四、构造函数

//无参构造函数,创建ReentrantLock实例,创建非公平的获取锁NonfairSync实例属性
public ReentrantLock() {sync = new NonfairSync();}

/**
 * 根据传入fair参数,创建非公平的获取锁NonfairSync实例或者公平的获取锁FairSync实例属性
 * 
 * @param fair {@code true} 创建FairSync实例属性,false创建NonfairSync实例属性 
 */
public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}
复制代码

五、内部类

  1. Sync内部类
    //AbstractQueuedSynchronizer的实现类,锁的获取和释放都是基于Sync,对AbstractQueuedSynchronizer不清楚的,可以看下另一篇AbstractQueuedSynchronizer源码分析 
    abstract static class Sync extends AbstractQueuedSynchronizer {
            private static final long serialVersionUID = -5179523762034025860L;
            
            //抽象方法,由NonfairSync和FairSync进行实现,公平的获取锁,还是非公平的获取锁
            abstract void lock();
            
            //在NonfairSync中使用到,非公平的获取锁
            //@param acquires 要获取的锁数
            final boolean nonfairTryAcquire(int acquires) {
                //获取当前要加锁的线程
                final Thread current = Thread.currentThread();
                //获取锁的状态,即AQS的属性state值
                int c = getState();
                //如果锁的状态等于0,表示处于无锁状态
                if (c == 0) {
                    //使用CAS更新锁状态,将锁状态更新成要获取的锁数
                    if (compareAndSetState(0, acquires)) {
                        //如果CAS更新锁状态成功,表示获取锁成功,将当前线程设置为占有锁的线程,即设置属性exclusiveOwnerThread为当前线程
                        setExclusiveOwnerThread(current);
                        //返回加锁成功 
                        return true;
                    }
                }
                //当前锁已被占有,判断占有锁的线程是否是当前线程,如果不是直接返回获取锁失败
                else if (current == getExclusiveOwnerThread()) {
                    //锁的原有状态加上传入进来要获取的锁数得到新的锁状态值
                    int nextc = c + acquires;
                    //如果计算出的状态值是负数,直接抛出Error错误,但是感觉这里会有些问题,比如原来的锁状态值为1,传入-1也会把锁给释放掉,这样加锁操作就变成了释放锁操作
                    if (nextc < 0) // overflow
                        throw new Error("Maximum lock count exceeded");
                    //设置锁的状态值为新的状态值nextc
                    setState(nextc);
                    //返回获取锁成功 
                    return true;
                }
                //返回获取锁失败
                return false;
            }
       
            //此方法在unLock方法中使用到,释放锁,修改锁的状态          
            //此方法只能在占有锁的线程调用,即unLock方法只能在持有锁的线程进行锁的释放
            //@param releases 要释放的锁数
            protected final boolean tryRelease(int releases) {
                //得到锁的新状态值
                int c = getState() - releases;
                //如果当前线程不是持有锁的线程,直接抛出IllegalMonitorStateException异常
                if (Thread.currentThread() != getExclusiveOwnerThread())
                    throw new IllegalMonitorStateException();
                //释放锁是否成功的标志位
                boolean free = false;
                //如果新的锁状态值为0
                if (c == 0) {
                    //将释放锁是否成功的标志位设置为成功
                    free = true;
                    //将占有独占锁的线程,即属性exclusiveOwnerThread置为空
                    setExclusiveOwnerThread(null);
                }
                //设置锁的状态 
                setState(c);
                //返回释放锁成功
                return free;
            }
      
      //判断当前线程是否是持有锁的线程,如果是返回true,否则返回false          protected final boolean isHeldExclusively() {
                //返回当前线程是否是持有锁的线程
                return getExclusiveOwnerThread() == Thread.currentThread();
            }
            
            //创建条件变量实例ConditionObject 
            final ConditionObject newCondition() {
                //返回新建的ConditionObject实例
                return new ConditionObject();
            }
                
            //获取占有锁的线程
            final Thread getOwner() {
                //如果当前处于无锁状态,返回null,否则返回占有锁的线程
                return getState() == 0 ? null : getExclusiveOwnerThread();
            }
            
            //得到锁的被获取数,也是锁的状态,只能在持有锁的线程操作才能获取到锁的状态,即锁的被获取数,否则直接返回0 
            final int getHoldCount() {
                return isHeldExclusively() ? getState() : 0;
            }
            
            //判断锁是否有被线程占有,即锁的状态是否是处于加锁的状态 
            final boolean isLocked() {
                //锁的状态不等于0,表明锁被线程占有,锁状态处于加锁状态
                return getState() != 0;
            }
            
            //从工作流中得到锁的对象,此方法目前没有使用到 
            private void readObject(java.io.ObjectInputStream s)
                throws java.io.IOException, ClassNotFoundException {
                s.defaultReadObject();
                //重新设置锁的状态
                setState(0); // reset to unlocked state
            }
    }
    复制代码
  2. NonfairSync内部类
    //Sync的实现类,非公平的获取锁
    static final class NonfairSync extends Sync {
            private static final long serialVersionUID = 7316153563782823691L;
            
            //Sync的抽象lock方法的重写,非公平的获取锁,在Reentrantlock的lock方法使用到
            final void lock() {
                //使用CAS将锁的状态从0更新成1,即加锁操作 
                if (compareAndSetState(0, 1))
                    //如果加锁成功,将当前线程设置为占有锁的线程,即设置属性exclusiveOwnerThread为当前线程
                    setExclusiveOwnerThread(Thread.currentThread());
                else
                    //NonfairSync从AQS中继承下来的方法,下面在讲锁的获取时会进行详细的介绍
                    acquire(1);
            }
            
            //NonfairSync重写了AbstractQueuedSynchronizer的tryAcquire模板方法,否则AQS中的tryAcquire方法会直接抛出UnsupportedOperationException异常
            //tryAcquire方法在acquire中使用到,非公平的获取锁都是基于此方法
            //@param acquires 要获取的锁数
            protected final boolean tryAcquire(int acquires) {
                //nonfairTryAcquire方法,在上面Sync内部中有进行介绍,非公平的获取锁,无需判断同步队列中前面是否有节点也在获取锁
                return nonfairTryAcquire(acquires);
            }
    }复制代码
  3. FairSync内部类
    //Sync的实现类,公平的获取锁
    static final class FairSync extends Sync {
            private static final long serialVersionUID = -3000897897090466540L;
             
            //Sync的抽象lock方法的重写,公平的获取锁,在Reentrantlock的lock方法使用到
            //FairSync的lock方法和NonfairSync的lock方法的区别是,NonfairSync的lock方法会尝试先获取锁,如果锁获取不到才会调用acquire方法,acquire内部也会尝试再获取锁,如果获取不到加入到同步队列中循环获取锁 
            final void lock() {
                //FairSync 从AQS中继承下来的方法,下面在讲锁的获取时会进行详细的介绍
                acquire(1);
            }
            
            //NonfairSync重写了AbstractQueuedSynchronizer的tryAcquire模板方法,否则AQS中的tryAcquire方法会直接抛出UnsupportedOperationException异常
            //tryAcquire方法在acquire中使用到,公平的获取都是基于此方法
            //tryAcquire方法和NonfairSync的tryAcquire方法不同的是需要调用hasQueuedPredecessors方法,判断头节点的下一个节点的线程是否是当前线程,如果不是表明前面有等待获取锁的线程
            //@param acquires 要获取的锁数
            protected final boolean tryAcquire(int acquires) {
                //获取当前要加锁的线程 
                final Thread current = Thread.currentThread();
                //获取锁的状态,即AQS的属性state值 
                int c = getState();
                //如果锁的状态等于0,表示处于无锁状态
                if (c == 0) {
                    //调用从AQS继承下来的hasQueuedPredecessors方法判断同步队列是否有获取锁的节点的线程,如果是就不执行直接获取锁
                    if (!hasQueuedPredecessors() &&
                        //如果AQS同步队列中没有等待要获取锁的节点的线程,使用CAS更新锁的状态 
                        compareAndSetState(0, acquires)) {
                        setExclusiveOwnerThread(current);
                        //返回公平的获取锁成功
                        return true;
                    }
                }
                //如果当前线程是占有锁的线程 
                else if (current == getExclusiveOwnerThread()) {
                    //锁的原有状态加上传入进来要获取的锁数得到新的锁状态值
                    int nextc = c + acquires;
                    //如果计算出的状态值是负数,直接抛出Error错误
                    if (nextc < 0)
                        throw new Error("Maximum lock count exceeded");
                    //设置锁的状态值为新的状态值nextc
                    setState(nextc);
                    //返回公平的获取锁成功
                    return true;
                }
                //返回公平的获取锁失败
                return false;
            }
    }复制代码

六、独占锁

  1. 独占锁获取
    1. 非公平获取锁
      //Reentrantlock的lock方法,直到获取写锁成功,不支持中断
      public void lock() {
          //sync的抽象lock方法,由Sync的两个子类FairSync和NonfairSync对lock进行重写,由于是非公平的获取锁,为此调用的是下面介绍的NonfairSync的重写的lock方法 
          sync.lock();
      }
      
      //NonfairSync重写Sync的lock方法
      final void lock() {
          //由于是非公平的获取锁,为此先使用CAS将锁的状态从0变成1,即加锁操作
          if (compareAndSetState(0, 1))
              //如果使用cas加锁成功,将当前线程设置wei
              setExclusiveOwnerThread(Thread.currentThread());
          else
              acquire(1);
      }
      
      public final void acquire(int arg) {
          if (!tryAcquire(arg) &&
              acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
              selfInterrupt();
      }
      
      protected final boolean tryAcquire(int acquires) {
          return nonfairTryAcquire(acquires);
      }
      
      final boolean nonfairTryAcquire(int acquires) {
                  final Thread current = Thread.currentThread();
                  int c = getState();
                  if (c == 0) {
                      if (compareAndSetState(0, acquires)) {
                          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;
      }
      
      final boolean acquireQueued(final Node node, int arg) {
              boolean failed = true;
              try {
                  boolean interrupted = false;
                  for (;;) {
                      final Node p = node.predecessor();
                      if (p == head && tryAcquire(arg)) {
                          setHead(node);
                          p.next = null; // help GC
                          failed = false;
                          return interrupted;
                      }
                      if (shouldParkAfterFailedAcquire(p, node) &&
                          parkAndCheckInterrupt())
                          interrupted = true;
                  }
              } finally {
                  if (failed)
                      cancelAcquire(node);
              }
      }
      
      private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
              int ws = pred.waitStatus;
              if (ws == Node.SIGNAL)
                  return true;
              if (ws > 0) {
                  do {
                      node.prev = pred = pred.prev;
                  } while (pred.waitStatus > 0);
                  pred.next = node;
              } else {
                  compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
              }
              return false;
      }
      
      private final boolean parkAndCheckInterrupt() {
              LockSupport.park(this);
              return Thread.interrupted();
      }
      
      private void cancelAcquire(Node node) {
              if (node == null)
                  return;
      
              node.thread = null;
      
              Node pred = node.prev;
              while (pred.waitStatus > 0)
                  node.prev = pred = pred.prev;
      
              Node predNext = pred.next;
      
              node.waitStatus = Node.CANCELLED;
      
              if (node == tail && compareAndSetTail(node, pred)) {
                  compareAndSetNext(pred, predNext, null);
              } else {
                  int ws;
                  if (pred != head &&
                      ((ws = pred.waitStatus) == Node.SIGNAL ||
                       (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
                      pred.thread != null) {
                      Node next = node.next;
                      if (next != null && next.waitStatus <= 0)
                          compareAndSetNext(pred, predNext, next);
                  } else {
                      unparkSuccessor(node);
                  }
      
                  node.next = node; // help GC
              }
      }
      
      private void unparkSuccessor(Node node) {
              
              int ws = node.waitStatus;
              if (ws < 0)
                  compareAndSetWaitStatus(node, ws, 0);
      
              Node s = node.next;
              if (s == null || s.waitStatus > 0) {
                  s = null;
                  for (Node t = tail; t != null && t != node; t = t.prev)
                      if (t.waitStatus <= 0)
                          s = t;
              }
              if (s != null)
                  LockSupport.unpark(s.thread);
      }
      复制代码
    2. 公平获取锁
      public void lock() {
          sync.lock();
      }
      
      final void lock() {
          acquire(1);
      }
      
      public final void acquire(int arg) {
          if (!tryAcquire(arg) &&
              acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
              selfInterrupt();
      }
      
      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;
      }
      
      public final boolean hasQueuedPredecessors() {
              Node t = tail; 
              Node h = head;
              Node s;
              return h != t &&
                  ((s = h.next) == null || s.thread != Thread.currentThread());
      }
      复制代码
  2. 独占锁释放
    public void unlock() {
        sync.release(1);
    }
    
    public final boolean release(int arg) {
            if (tryRelease(arg)) {
                Node h = head;
                if (h != null && h.waitStatus != 0)
                    unparkSuccessor(h);
                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);
                }
                setState(c);
                return free;
    }复制代码

以上所述就是小编给大家介绍的《ReentrantLock源码分析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

3D打印

3D打印

[美]胡迪•利普森,梅尔芭•库曼 / 赛迪研究院专家组 / 中信出版社 / 2013-4 / 49.00元

《3D打印:从想象到现实》内容简介:你需要一把功能强大的锤子?你需要一双精致无比的鞋子?你需要给孩子准备奇异的玩具?你需要一顿精美的晚餐?只管打印出来就行了。《3D打印:从想象到现实》带你走进3D打印的世界,认识一下当下这个最酷的东西——它将从想象变成现实,并带来一场深刻的社会革命。 书中讲述了3D打印技术的突破性发展,以及3D打印技术将如何应用在学校、厨房、医院等场所的。《3D打印:从想象......一起来看看 《3D打印》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

SHA 加密
SHA 加密

SHA 加密工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具