Lock源码学习笔记

1、基础使用

//声明锁,默认为true非公平锁 
static Lock lock1=new ReentrantLock();
public static void main(String[] args) {
    try{
        lock1.lock();
        // todo
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        lock1.unlock();
    }
}

2、非公平锁源码追踪

2.1 非公平锁加锁lock()

final void lock() {
     //(1)首先通过cas设置state变量值,如果设置成功则返回
     if (compareAndSetState(0, 1))
         //设置当前线程为占有锁的线程
         setExclusiveOwnerThread(Thread.currentThread());
     else
         acquire(1);
 }


 public final void acquire(int arg) {
     //!tryAcquire(arg) 如果获取锁失败则执行acquireQueued(addWaiter(Node.EXCLUSIVE), 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) {
        //这个地方与公平锁不同的时直接设置state标识,不在判断aqs是否为空
        if (compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    //判断获取锁的线程是否是当前线程
    else if (current == getExclusiveOwnerThread()) {
        //重入次数加1
        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
    //获取尾节点,判断是否是空节点,如果是空节点则初始化节点enq(node)
    Node pred = tail;
    if (pred != null) {
        //将当前节点的prev指针指向尾节点
        node.prev = pred;
        //通过CAS将当前节点设置为tail节点
        if (compareAndSetTail(pred, node)) {
            //将前面节点的next指针指向当前节点
            pred.next = node;
            return node;
        }
    }
    //初始化节点
    enq(node);
    return node;
}

//这里采用自旋操作,避免节点初始化失败导致AQS队列异常
private Node enq(final Node node) {
    for (;;) {
        //获取尾节点
        Node t = tail;
        if (t == null) { // Must initialize
            //如果尾节点为空,通过CAS初始化head节点
            if (compareAndSetHead(new Node()))
                //将尾节点同时指向头节点所在的节点
                tail = head;
        } else {
            //将当前节点的prev指针指向节点t
            node.prev = t;
            //通过CAS将当前节点设为tail节点
            if (compareAndSetTail(t, node)) {
                //将节点t的next指针指向当前节点
                t.next = node;
                return t;
            }
        }
    }
}

//自旋锁和阻塞操作
final boolean acquireQueued(final Node node, int arg) {
    boolean failed = true;
    try {
        boolean interrupted = false;
        for (;;) {
            //获取当前节点的prev指向的节点
            final Node p = node.predecessor();
            //如果当前节点的prev指向head节点,尝试竞争锁
            //这个地方判断节点是否是第一个节点
            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);
    }
}

 

2.3 释放锁unlock()

public void unlock() {
     sync.release(1);
 }

  public final boolean release(int arg) {
      //修改state标记,当值为0返回true
      if (tryRelease(arg)) {
          Node h = head;
          //waitStatus初始化状态为0
          if (h != null && h.waitStatus != 0)
              unparkSuccessor(h);
          return true;
      }
      return false;
  }

protected final boolean tryRelease(int releases) {
    //重入次数减1
    int c = getState() - releases;
    //如果当前线程不是锁持有线程抛异常
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    //如果state为0则清空当前持锁线程(重入次数为0)
    if (c == 0) {
        free = true;
        setExclusiveOwnerThread(null);
    }
    //修改state值
    setState(c);
    return free;
}


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;
    	//如果head节点后面的节点为空或者线程已经取消,则将对应的节点移除
        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;
        }
    //如果head后面的节点不为空,则唤醒对应节点的线程
        if (s != null)
            LockSupport.unpark(s.thread);
    }

关键变量描述

类型 属性名 描述
int waitStatus 等待状态
Node prev 指向队列的前一个
Node next 指向队列中后一个节点
Thread thread Node的持有线程
Node nextWaiter 下一个等待condition的Node
请登录后发表评论

    没有回复内容