concurrent-lock-ReentrantLock
这个类抓住两个方法,一个是lock,一个是unlock。
(1)lock方法:
1)只有通过tryAcquire方法没有获取到锁的线程会被封装成Node加入到阻塞队列;
2)acquireQueued方法:
1.2.1 如果没有获取到锁,则调用park对线程进行阻塞;
1.2.2 其他线程调用unpark对阻塞线程解除阻塞后,进行抢锁,抢到后head后移,将抢到锁的线程移出阻塞队列。
(2)unlock方法:
1)释放锁(onwer置为null,state置为0);
2)对阻塞队列中head指向的后一个线程接触阻塞(对应1.2.2)。
为什么不关心是否成功却还要设置呢?
注意这里的Node实际就是head
如果设置成功,即head.waitStatus=0,则可以让这时即将被阻塞的线程有机会再次调用tryAcquire获取锁。
也就是让shouldParkAfterFailedAcquire方法里的compareAndSetWaitStatus(pred, ws, Node.SIGNAL)执行失败返回false,这样就能再有机会再tryAcquire了
如果设置失败,新跟随在head后面的线程被阻塞,但是没关系,下面的代码会立即将这个阻塞线程释放掉
对应