1.lock()方法主要是使用sync调用release()方法;这个方法,不像之前acquire方法那样可能会出现不同得方法,release()方法是AQS的方法。

alt

尝试释放锁,如果释放锁成功,则唤醒下一个等待的线程;

alt

tryRelease()主要是把资源被重入的次数依次减掉,如果当前的线程不是独占锁的线程,那么意味着出错了,于是抛出异常; 定义一个布尔量为free,并且为false,表示此时资源还没被释放。接着定义了一个c== 0,那么表示没有线程占用资源,就把free改为true,并且把独占线程我设置为null;,最后把status设置为0,表示资源被释放调了;

接着奏if语句后面的内容

alt

首先先获取头结点,如果头结点为null,则表示CLH队列为空,那么就不要唤醒操作了;由于之前的修改,就会使得头结点一定不为0,所以就会执行unparkSuccessor(h);这个函数源码:

alt alt

首先获取头结点的ws,通过cas的方式,把头结点的ws变为0;(在此之前是singal,说明此节点不参与监控下一个节点了);

于是对自己节点的ws更新操作完成之后,就需要拿到下一个节点,如果这个节点为null或者是他的ws大于0,那么此节点就不应当被唤醒;于是此节点设为null,并且从尾巴开始,往队首遍历,只要p不为head,并且p不为nll,只要节点p的ws小于0,那么就把s节点指向当前的p节点,于是循环的最后,s节点就指向了队列中,第一个ws小于0的节点;

接着执行最后一个if语句,假设头结点的下一个节点不为null,那么就会直接执行第三个if语句,所以这个节点就是需要被唤醒的线程,使用unpark()方法唤醒线程。但是如果头节点的下一个节点是null,那么怎么保证呢;就进入第二个if语句,如果这个头节点的下一个节点是null,那么先获取tail,并且使用for循环一次遍历队列,只要这个节点不是头结点,满足这个节点不为null。就改变p节点的指向,相当于向队首方向移动了p节点, 如果此时p节点ws值小于0,那么就让s节点指向当前的p节点(s的含义其实就是singal,代表被singal唤醒额线程);于是使用unpark唤醒线程;

注意:tryRelease()方法不是释放线程,而是释放资源,修改资源的状态;真正释放资源的是unparkSuccessor(),资源是释放完毕,唤醒线程用于抢锁;