private static int sum = 0;private static Lock lock = new ReentrantLock();public static void main(String[] args) throws InterruptedException {for (int i = 0; i < 3; i++) {Thread thread = new Thread(() -> {//加锁lock.lock();try {for (int j = 0; j < 10000; j++) {sum++;}} finally {// 解锁lock.unlock();}});thread.start();}Thread.sleep(2000);System.out.println(sum);}
ReentrantLock默认是非公平锁NonfairSync,公平锁与非公平锁的区别:非公平锁会先进行一次CAS。
非公平锁:
公平锁:
上面代码的流程:
thread0
- 会先进入到lock方法,然后进行compareAndSetState,此时compareAndSetState是能成功的,因为这时候的status=0

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

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

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

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

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

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


- 然后执行acquireQueued

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

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

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

- 然后同样也会执行acquireQueued,然后把node的前驱节点thread1的waitState修改为-1,然后被挂起。
解锁unLock
- 实际调用方法release,arg=1

- 先执行tryRelease,releases=1

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

�
�
�
�
�
