JUC代码浅析[2]——基于AQS的锁ReentrantLock
???????? ReentrantLock是使用比较普遍的一个可重入锁,它是互斥的,一个锁只能被一个线程占有。它的方法基本都是委托给继承AQS的Sync实现的。其中Sync有两种实现,公平和非公平。Sync使用state(通过AQS暴露的getState和setState方法)保存线程的获取次数。总的策略为state次数为0时可以获得锁。大于0时,如果当前线程已经拥有该锁则可再次获得,否则进入AQS的调度逻辑(<JUC代码浅析——同步器AQS>中介绍)。下面为非公平ReentrantLock的NonfairSync实现,
??????? final void lock() {
??????????? if (compareAndSetState(0,1))
???????????????setExclusiveOwnerThread(Thread.currentThread());
??????????? else
?? ?????????????acquire(1);
??????? }
如果state次数为0的话,获得成功并设置当前线程为锁的拥有者。
否则进入AQS调度,acquire(1)方法使用tryAcquire尝试获得,这里重载的tryAcquire调用的是nonfairTryAcquire方法
??????? final boolean nonfairTryAcquire(int acquires) {
??????????? final Thread current = Thread.currentThread();
??????????? int c = getState();
?????????? //如果当前重进入数为0,有机会取得锁
??????????? if (c == 0) {
?????????? //获得成功并设置当前线程为锁的拥有者
??????????????? if (compareAndSetState(0, acquires)) {
???????????????????setExclusiveOwnerThread(current);
? ??????????????????return true;
??????????????? }
??????????? }
?????? //如果当前线程已经拥有该锁则可再次获得
??????????? else if (current == getExclusiveOwnerThread()) {
??????????????? int nextc = c + acquires;
??????????????? if (nextc < 0) // overflow
??????????????????? throw new Error("Maximumlock count exceeded");
??????????????? setState(nextc);
??????????????? return true;
??????????? }
?????? //都不满足,则进入AQS队列等待调度
??????????? return false;
??????? }
?
公平ReentrantLock的FairSync实现
protected final boolean tryAcquire(int acquires) {
??????????? final Thread current = Thread.currentThread();
??????????? int c = getState();
?????? //如果当前重进入数为0,有机会取得锁
??????????? if (c == 0) {
?????????? //如果当前线程是第一个等待者,获得成功并设置当前线程为锁的拥有者
??????????????? if (isFirst(current) &&
??????????????????? compareAndSetState(0,acquires)) {
???????????????????setExclusiveOwnerThread(current);
??????????????????? return true;
??????????????? }
??????????? }
?????? //如果当前线程已经拥有该锁则可再次获得
??????????? else if (current == getExclusiveOwnerThread()) {
??????????????? int nextc = c + acquires;
??????????????? if (nextc < 0)
??????????????????? throw new Error("Maximumlock count exceeded");
??????????????? setState(nextc);
??????????????? return true;
??????????? }
?????? //都不满足,则进入AQS队列等待调度
??????????? return false;
??????? }
?
?????? fairSync和NonfairSync的tryRelease方法是同一个,比较简单,就是改变一下state次数,如果需要的话把拥有者线程置为null
??????? protected final boolean tryRelease(int releases) {
??????????? int c = getState() - releases;
??????????? if (Thread.currentThread() !=getExclusiveOwnerThread())
??????????????? throw new IllegalMonitorStateException();
??????????? boolean free = false;
??????????? if (c == 0) {
??????????????? free = true;
??????????????? setExclusiveOwnerThread(null);
?????? ?????}
??????????? setState(c);
??????????? return free;
??????? }
?
?????? 公平和非公平的区别就在于,尝试进入的时候需要判断当前线程是否是队列的第一个,是第一个才能进入。这样AQS在调度的时候就会阻塞掉很多线程,性能差别就比较大。ReentrantLock只支持互斥模式,没有共享模式
?