AQS框架下的锁都是实现Lock接口并实现tryAcquire方法,在tryAcquire方法中对state变量进行修改来改变锁的状态。
cas修改state的状态,如果成功设置当前重入锁的拥有者是当前线程。cas对当前state的期待值为0,所以一个线程如果是重入自己持有的锁,在这一步是无法成功的。
final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); }
如果cas失败会调用acquire(1),即调用tryAcquire(1),最终调用的是nonfairAcquire(1),该方法是非公平锁的核心实现。
非公平重入锁的tryAcquire实现相对简单
protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); }
/** * Performs non-fair tryLock. tryAcquire is implemented in * subclasses, but both need nonfair try for trylock method. */ final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); 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("Maximum lock count exceeded"); setState(nextc); return true; } return false; }
公平锁的lock方法中直接调用了acquire,而非公平锁lock方法中先cas,cas失败后才调用的acquire。这是公平性和非公平性的体现,acquire失败后会进入队列,AQS队列中的线程只有pre是head才可以尝试获得锁,即aqs通过队列的方式维护了公平性,如果把所有锁的获得都交给aqs去管理,那么锁就是公平的。相应的如果在加入aqs之前先自己尝试获取锁,那么这个锁就未必是公平的。例如:A线程获取锁的时候发现state不是0,失败进入AQS队列,B线程尝试获取锁的时候state恰好变成0,由于A线程在AQS队列尾部,A线程不具有争取锁的资格,所以B线程获得锁A没有获得锁,这就是非公平性的体现。
final void lock() { acquire(1); }
这里同样分为两个部分
/** * Fair version of tryAcquire. Don‘t grant access unless * recursive call or no waiters or is first. */ protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }
公平锁和非公平锁的释放没有区别,都是静态内部类sync中的tryRelease方法。
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; }
这些获得锁的方法都是公平锁和非公平锁没有区别。
在获得锁失败被park时候能够相应中断,实现比较简单,直接调用AQS里的方法。
非阻塞获取锁,类似NIO。如果lock没有被别的线程持有,那么tryLock会立即返回true,这种行为其实是一种非公平的锁,另外从它调用的方法nonfairTryAcquire也可以看出这一点。这也就意味着如果你申请了一个公平锁,调用一个公平锁的tryLock它的行为也是非公平的。如果lock此时被别的线程持有,tryLock会返回false。
public boolean tryLock() { return sync.nonfairTryAcquire(1); }
final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); 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("Maximum lock count exceeded"); setState(nextc); return true; } return false; }
原文:https://www.cnblogs.com/AshOfTime/p/10890108.html