一、方法一
final void lock() { //第一个线程获取锁,如果成功,则直接返回,这种情况是最快的 if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else //如果不是第一个线程获取锁,则加锁流程 acquire(1); }
二、方法二
// 3个主要方法 tryAcquire、addWaiter、 acquireQueued public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
三、方法三
//非公平锁,尝试获取锁 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; }
四、方法四
//节点放入到队列的过程 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; //如果tail不为空,即已经有队列了 if (pred != null) { //当前线程的节点,前置节点设置为原来链表的tail node.prev = pred; //如果队列此时尾部节点还是pred,则设置node节点为尾部节点 if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } //当前锁中还没有队列,创建一个新队列 enq(node); return node; }
五、方法五
//构建一个队列,用来排队 private Node enq(final Node node) { //循环2次创建一个队列 for (;;) { Node t = tail; //tail节点为空,说明 还没有队列 if (t == null) { // Must initialize ,第一个循环会进到这个里面 //创建一个空的node,并且空节点设置为头节点 if (compareAndSetHead(new Node())) //tail 也指向这个空节点 tail = head; } else { //当前节点的prev ,指向 前面 空的头节点 node.prev = t; // 把 当前线程的 node节点,放到队列的尾部 if (compareAndSetTail(t, node)) { // 把原tail节点的next 指向当前节点,即 空的node节点(头节点)的next指向当前节点 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); } }
七、方法七
设置当前节点的前一个节点waitStatus 状态为 SIGNAL ,这样前一个节点释放锁以后才会唤醒后面的线程节点 private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { int ws = pred.waitStatus; if (ws == Node.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 { 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. */ compareAndSetWaitStatus(pred, ws, Node.SIGNAL); } return false; }
八、方法八-线程阻塞
private final boolean parkAndCheckInterrupt() { //线程阻塞,当被唤醒以后会接着这个地方继续执行 LockSupport.park(this); return Thread.interrupted(); }
到此线程的加锁过程完成