1. private static int sum = 0;
  2. private static Lock lock = new ReentrantLock();
  3. public static void main(String[] args) throws InterruptedException {
  4. for (int i = 0; i < 3; i++) {
  5. Thread thread = new Thread(() -> {
  6. //加锁
  7. lock.lock();
  8. try {
  9. for (int j = 0; j < 10000; j++) {
  10. sum++;
  11. }
  12. } finally {
  13. // 解锁
  14. lock.unlock();
  15. }
  16. });
  17. thread.start();
  18. }
  19. Thread.sleep(2000);
  20. System.out.println(sum);
  21. }

ReentrantLock默认是非公平锁NonfairSync,公平锁与非公平锁的区别:非公平锁会先进行一次CAS。
非公平锁:
截屏2022-03-23 00.53.56.png
公平锁:
截屏2022-03-23 00.54.11.png

上面代码的流程:

thread0

  • 会先进入到lock方法,然后进行compareAndSetState,此时compareAndSetState是能成功的,因为这时候的status=0

截屏2022-03-23 00.53.56.png

  • 然后执行setExclusiveOwnerThread,也就是把当前线程赋值给exclusiveOwnerThread属性。exclusiveOwnerThread主要是用作重入锁判断的

截屏2022-03-23 01.04.34.png

  • 此时thread0获取锁,执行业务逻辑操作

截屏2022-03-23 01.07.18.png

thread1

  • 先进入到lock方法,然后进行compareAndSetState,此时的compareAndSetState是失败的,因为thread0已经把status修改为1,所以thread1会执行acquire(1)方法。

截屏2022-03-23 01.18.00.png

  • tryAcquire实际调用的是nonfairTryAcquire,返回的是false。

03-22ReentrantLock源码分析 - 图7

  • 然后会执行acquireQueued(addWaiter(Node.EXCLUSIVE), arg),Node.EXCLUSIVE是独占模式。
    • 先执行addWaiter(Node.EXCLUSIVE),添加到等待队列里面。等待队列是带头节点的双向链表。

03-22ReentrantLock源码分析 - 图8

  • enq(node),入队列操作。

03-22ReentrantLock源码分析 - 图9
03-22ReentrantLock源码分析 - 图10

  • 然后执行acquireQueued

03-22ReentrantLock源码分析 - 图11

  • 继续执行shouldParkAfterFailedAcquire,返回false。而且把node的前驱节点的waitStatus修改为-1

03-22ReentrantLock源码分析 - 图12

  • 因为是for(;;)循环,会继续执行,因为此时node的前驱节点的waitStatus修改为-1,所以再次调用shouldParkAfterFailedAcquire返回了true。然后去执行parkAndCheckInterrupt()方法。parkAndCheckInterrupt会把当前的thread1挂起。

截屏2022-03-23 03.17.44.png

thread2

  • 前面和thread1的逻辑一样
  • 然后执行addWaiter(Node mode)

03-22ReentrantLock源码分析 - 图14

  • 然后同样也会执行acquireQueued,然后把node的前驱节点thread1的waitState修改为-1,然后被挂起。

解锁unLock

  • 实际调用方法release,arg=1

截屏2022-03-23 03.37.21.png

  • 先执行tryRelease,releases=1

03-22ReentrantLock源码分析 - 图16

  • 然后调用unparkSuccessor,node是头节点

03-22ReentrantLock源码分析 - 图17