Java多线程框架源码阅读之---ReentrantLock
2017-11-15 21:06
393 查看
ReentrantLock基于Sync内部类来完成锁。Sync有两个不同的子类NonfairSync和FairSync。Sync继承于AbstractQueuedSynchronizer。
ReentrantLock的大部分方法都是基于AbstractQueuedSynchronizer实现,大部分仅仅是对AbstractQueuedSynchronizer的转发。因此,了解AbstractQueuedSynchronizer就非常重要。
作为AbstractQueuedSynchronizer的实现者需要实现isHeldExclusively,tryAcquire,tryRelease,(可选tryAcquireShared,tryReleaseShared)
那么我们看看对于一个常用的套路,ReentrantLock是如何实现同步的
lock.lock()内部实现为
我们先看一下Sync和NonfairSync的实现。
上面的代码中,调用了AQS的acquire。下面看一下AQS的实现
对于非公平的锁,tryAcquire会调用到NonfairSync里面的tryAcquire,而tryAcquire又会调用到Sync的nonfairTryAcquire。
addWaiter方法用于创建一个节点(值为当前线程)并维护一个双向链表。注意head是一个假节点,97影院 阻塞的节点是作为head后面的节点出现的。
ReentrantLock的大部分方法都是基于AbstractQueuedSynchronizer实现,大部分仅仅是对AbstractQueuedSynchronizer的转发。因此,了解AbstractQueuedSynchronizer就非常重要。
作为AbstractQueuedSynchronizer的实现者需要实现isHeldExclusively,tryAcquire,tryRelease,(可选tryAcquireShared,tryReleaseShared)
那么我们看看对于一个常用的套路,ReentrantLock是如何实现同步的
for(int j=0;j<10000000;j++){ lock.lock(); try{ i++; }finally { lock.unlock(); } }
lock.lock()内部实现为
public void lock() { sync.lock(); }
我们先看一下Sync和NonfairSync的实现。
abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -5179523762034025860L; /** * Performs {@link Lock#lock}. The main reason for subclassing * is to allow fast path for nonfair version. */ abstract void lock(); /** * Performs non-fair tryLock. tryAcquire is implemented in * subclasses, but both need nonfair try for trylock method. */ final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); //如果没有锁上,则设置为锁上并设置自己为独占线程 if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } //如果锁上了,而且独占线程是自己,那么重新设置state+1,并且返回true else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } //否则返回false return false; } protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != www.97yingyuan.org getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; } protected final boolean isHeldExclusively() { // While we must in general read state before owner, // we don't need to do so to check if current thread is owner return getExclusiveOwnerThread() == Thread.currentThread(); } final ConditionObject newCondition() { return new ConditionObject(); } // Methods relayed from outer class final Thread getOwner() { return getState() == 0 ? null : getExclusiveOwnerThread(); } final int getHoldCount() { return isHeldExclusively() ? getState() : 0; } final boolean isLocked() { return getState() != 0; } /** * Reconstitutes the instance from a stream (that is, deserializes it). */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); setState(0); // reset to unlocked state } }
static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; /** * Performs lock. Try immediate barge, backing up to normal * acquire on failure. */ final void lock() { //如果没有人锁上,那么就设置我自己为独占线程,否则再acquire一次 if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else //调用到了AQS的acquire里面 acquire(1); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } }
上面的代码中,调用了AQS的acquire。下面看一下AQS的实现
public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
对于非公平的锁,tryAcquire会调用到NonfairSync里面的tryAcquire,而tryAcquire又会调用到Sync的nonfairTryAcquire。
addWaiter方法用于创建一个节点(值为当前线程)并维护一个双向链表。注意head是一个假节点,97影院 阻塞的节点是作为head后面的节点出现的。
private Node addWaiter(Node mode) { Node node = new Node(Thread.currentThread(), mode); // Try the fast path of enq; backup to full enq on failure Node pred = tail; if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } enq(node); return node; } private Node enq(final Node node) { for (;;) { Node t = tail; if (t == null) { // Must initialize if (compareAndSetHead(new Node())) tail = head; } else { node.prev = t; if (compareAndSetTail(t, node)) { t.next = node; return t; } } } }
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); } }
相关文章推荐
- J.U.C并发框架源码阅读(三)ReentrantLock
- JAVA源码阅读-集合框架(一)
- 《java.util.concurrent 包源码阅读》25 Fork/Join框架之Fork与Work-Stealing(重写23,24)
- 《java.util.concurrent 包源码阅读》26 Fork/Join框架之Join
- 《java.util.concurrent 包源码阅读》22 Fork/Join框架的初体验
- 《java.util.concurrent 包源码阅读》24 Fork/Join框架之Work-Stealing
- soy轻量级java应用框架在线演示和源码下载
- [jjzhu学java]之JDK集合框架源码分析
- Android源码分析:Java的Media Scanner层(阅读笔记)
- CI框架源码阅读---------Output.php
- Java多线程系列--“JUC集合”01之 框架
- Java源码阅读-ArrayList
- Mavlink地面站编写之五—MP源码多线程读写框架分析
- 分享java旷课版的SSM框架源码
- 【双旦献礼】Portal-Basic Java Web 应用开发框架 v3.0.1 正式发布(源码、示例及文档)
- 【双旦献礼】Portal-Basic Java Web 应用开发框架 v3.0.1 正式发布(源码、示例及文档)
- Java中IO框架——InputStream源码解析
- Java类集框架之HashMap(JDK1.8)源码剖析
- Java源码阅读之FutureTask
- 【Java多线程】Java的MapReduce框架ForkJoin