concurrent-4-AQS-ReentrantLock-Lock

来源:互联网 发布:excel 删除重复数据 编辑:程序博客网 时间:2024/05/22 03:18
    可重入锁源码解析。

AbstractQueuedSynchronizer#Node 节点信息

tatic final class Node {        /** Marker to indicate a node is waiting in shared mode */        static final Node SHARED = new Node();   //共享模式        /** Marker to indicate a node is waiting in exclusive mode */        static final Node EXCLUSIVE = null;   //独占模式        /** waitStatus value to indicate thread has cancelled */        static final int CANCELLED =  1;  ////因为超时或者中断,node会被设置成取消状态,被取消的节点时不会参与到竞争中的,会一直保持取消状态不会转变为其他状态;         /** waitStatus value to indicate successor's thread needs unparking */        static final int SIGNAL    = -1; //若节点的后继节点被阻塞,当前节点释放锁或者取消的时候需要唤醒后继者。         /** waitStatus value to indicate thread is waiting on condition */        static final int CONDITION = -2;   //表明线程在等待中        /**         * waitStatus value to indicate the next acquireShared should         * unconditionally propagate         */        static final int PROPAGATE = -3;   //该状态表示下一次节点如果是Shared的,则无条件获取锁。        volatile int waitStatus;   //节点的状态值        volatile Node prev;   //前节点        volatile Node next;  //后节点          volatile Thread thread;  //节点关联线程          Node nextWaiter;   //连接到下一个节点等待条件,或特殊值共享

lock获取资源

ReenTrantLock#lock

//加锁 public void lock() {        sync.lock();   //实际为封装AQS实现类    }

ReenTrantLock#NonfairSync#lock

   final void lock() {            if (compareAndSetState(0, 1))   //尝试cas操作,抢占锁                setExclusiveOwnerThread(Thread.currentThread());   //标记独占锁为被当前线程            else                acquire(1);     //尝试获取锁(AQS方法)        }

AbstractQueuedSynchronizer#acquire

public final void acquire(int arg) {        if (!tryAcquire(arg) &&  //尝试直接去获取资源,如果成功则直接返回            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))            //addWaiter:线程加入等待队列的尾部,并标记为独占模式            //acquireQueued 尝试获取资源,如果获取了资源被且没有被标记为中断则返回false,否则返回true            selfInterrupt();  //等待中标记中断,获取资源后自我中断    }

ReenTrantLock#NonfairSync#tryAcquire

protected final boolean tryAcquire(int acquires) {            return nonfairTryAcquire(acquires);   //非公平锁的获取资源方式        }

ReenTrantLock#NonfairSync#nonfairTryAcquire

 final boolean nonfairTryAcquire(int acquires) {            final Thread current = Thread.currentThread();            int c = getState();  //获取状态            if (c == 0) {                //如果是0,则尝试cas操作加锁,无须进入队列排队,可能被其它线程抢占                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;        }

AbstractQueuedSynchronizer#addWaiter

 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) {   //如果pred 不为null 则非初始化状态 尝试cas操作,失败则enq进行循环cas操作            node.prev = pred;            if (compareAndSetTail(pred, node)) {  //尝试入队列                pred.next = node;                return node;            }        }        enq(node);  //循环cas入sync队列        return node;    }

AbstractQueuedSynchronizer#enq

private Node enq(final Node node) {        for (;;) {            Node t = tail;   //指定 t 为 尾部节点            if (t == null) { // Must initialize   //初始化                if (compareAndSetHead(new Node()))   //将head位设置为新节点                    tail = head;            } else {                node.prev = t;    //将node 节点的prev 标记为 tail节点(可能有其它线程在重复改变tail)                if (compareAndSetTail(t, node)) {   //如果cas操作成功,那么将node节点标记为tail节点                    t.next = node;     //同时将t(上一次的tail节点)的下一个节点标记为node(新的tail节点)                    return t;                }            }        }    }

AbstractQueuedSynchronizer#acquireQueued

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)) {   //如果前节点是head,则尝试获取资源!!!!!队列中头部节点先获取资源                    setHead(node);   //获取成功,将本节点设置为head节点                    p.next = null; // help GC                    failed = false;                    return interrupted;  //成功获取资源并且未被中断                }                //shouldParkAfterFailedAcquire:判断在获取资源失败后,是否应该睡眠(根据前节点的waitStatus)。                //parkAndCheckInterrupt:睡眠的同时,判断是否有中断状态                if (shouldParkAfterFailedAcquire(p, node) &&                    parkAndCheckInterrupt())                    interrupted = true;            }        } finally {            if (failed)                cancelAcquire(node);  //如果失败则取消获取资源        }    }

AbstractQueuedSynchronizer#shouldParkAfterFailedAcquire

 private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {        int ws = pred.waitStatus;  //下一个节点的等待状态        if (ws == Node.SIGNAL)    //signal 状态则正常放回            /*             * This node has already set status asking a release             * to signal it, so it can safely park.             */        return true;        if (ws > 0) {            /*             * Predecessor was cancelled. Skip over predecessors and             * indicate retry.             */            do {   //如要将所有>0 即取消的节点都排除                node.prev = pred = pred.prev;            } while (pred.waitStatus > 0);            pred.next = node;        } else {            /*             * waitStatus must be 0 or PROPAGATE.  Indicate that we             * need a signal, but don't park yet.  Caller will need to             * retry to make sure it cannot acquire before parking.             */            //cas 操作将节点的waitStatus标记为signal状态            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);        }        return false;    }

UnLock

ReenTrantLock#unLock

 public void unlock() {        sync.release(1);   //释放资源    }

AbstractQueuedSynchronizer#release

public final boolean release(int arg) {        if (tryRelease(arg)) {  //尝试释放锁成功(可能重入了多次锁)            Node h = head;            //如果没有队列外的线程获取锁,那么获取锁资源的一定是队列头,此处需要唤醒其它线程            //从队尾开始唤醒,因为队尾可能一直会新加入线程,双端队列容易死循环            if (h != null && h.waitStatus != 0)                unparkSuccessor(h);            return true;        }        return false;    }

ReenTrantLock#tryRelease

protected final boolean tryRelease(int releases) {            int c = getState() - releases;  //获取当前线程状态值            if (Thread.currentThread() != getExclusiveOwnerThread())                throw new IllegalMonitorStateException();            boolean free = false;            if (c == 0) {   //如果线程状态为0,则表示已经释放了锁                free = true;                setExclusiveOwnerThread(null);            }            setState(c);   //设置状态            return free;        }

AbstractQueuedSynchronizer#unparkSuccessor

private void unparkSuccessor(Node node) {        /*         * If status is negative (i.e., possibly needing signal) try         * to clear in anticipation of signalling.  It is OK if this         * fails or if status is changed by waiting thread.         */        int ws = node.waitStatus;  //获取线程的下一个节点的等待状态        if (ws < 0)            compareAndSetWaitStatus(node, ws, 0);  //标记该节点线程已经被释放        /*         * Thread to unpark is held in successor, which is normally         * just the next node.  But if cancelled or apparently null,         * traverse backwards from tail to find the actual         * non-cancelled successor.         */        Node s = node.next;        //如果下一个节点为null,或者状态为取消        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);    }