ReentrantLock源码分析

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

内容简介: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源码分析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

The Effective Engineer

The Effective Engineer

Edmond Lau / The Effective Bookshelf, Palo Alto, CA. / 2015-3-19 / USD 39.00

Introducing The Effective Engineer — the only book designed specifically for today's software engineers, based on extensive interviews with engineering leaders at top tech companies, and packed with h......一起来看看 《The Effective Engineer》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具