内容简介: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的源码分析。
还没写完,有空继续写
二、类关系
//独占锁的接口,以下方法在下面都会详细的介绍 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(); } 复制代码
五、内部类
- 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 } } 复制代码
- 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); } }复制代码
- 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; } }复制代码
六、独占锁
- 独占锁获取
- 非公平获取锁
//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); } 复制代码
- 公平获取锁
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()); } 复制代码
- 独占锁释放
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源码分析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 以太坊源码分析(36)ethdb源码分析
- [源码分析] kubelet源码分析(一)之 NewKubeletCommand
- libmodbus源码分析(3)从机(服务端)功能源码分析
- [源码分析] nfs-client-provisioner源码分析
- [源码分析] kubelet源码分析(三)之 Pod的创建
- Spring事务源码分析专题(一)JdbcTemplate使用及源码分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。