/*** l.k
*
* 限制可以重入次数的锁,默认是2次
**/
public class ReenterLimitedLock implementsLock, java.io.Serializable {private static final long serialVersionUID = 7373984872572414699L;private finalSync sync;/*** Creates an instance of {@codeReenterLimitedLock}.
* This is equivalent to using {@codeReenterLimitedLock(false)}.*/
publicReenterLimitedLock() {
sync= new NonfairSync(2);
}public ReenterLimitedLock(intreenterLimit) {
sync= newNonfairSync(reenterLimit);
}public ReenterLimitedLock(boolean fair, intreenterLimit) {
sync= fair ? new FairSync(reenterLimit) : newNonfairSync(reenterLimit);
}public ReenterLimitedLock(booleanfair) {
sync= fair ? new FairSync(2) : new NonfairSync(2);
}abstract static class Sync extendsAbstractQueuedSynchronizer {private static final long serialVersionUID = -5179523762034025860L;private booleanexceeded;private intreenterLimit;public Sync(intreenterLimit) {this.reenterLimit =reenterLimit;
}abstract voidlock();final boolean nonfairTryAcquire(int acquires) throwsMaximumLockCountExceededException {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
if (nextc >reenterLimit) { // 关键
exceeded= true;//return false;//throw new IllegalStateException("Maximum lock count exceeded" + 2);
throw newMaximumLockCountExceededException(reenterLimit);
}
setState(nextc);return true;
}return false;
}protected final boolean tryRelease(intreleases) {if(isExceeded()) {return false;
}int c = getState() -releases;if (Thread.currentThread() !=getExclusiveOwnerThread())throw newIllegalMonitorStateException();boolean free = false;if (c == 0) {
free= true;
setExclusiveOwnerThread(null);
}
setState(c);returnfree;
}protected final booleanisHeldExclusively() {//While we must in general read state before owner,//we don't need to do so to check if current thread is owner
return getExclusiveOwnerThread() ==Thread.currentThread();
}finalConditionObject newCondition() {return newConditionObject();
}//Methods relayed from outer class
finalThread getOwner() {return getState() == 0 ? null: getExclusiveOwnerThread();
}final intgetHoldCount() {return isHeldExclusively() ? getState() : 0;
}final booleanisLocked() {return getState() != 0;
}/*** Reconstitutes the instance from a stream (that is, deserializes it).*/
private voidreadObject(java.io.ObjectInputStream s)throwsjava.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); //reset to unlocked state
}public booleanisExceeded() {returnexceeded;
}public void setExceeded(booleanexceeded) {this.exceeded =exceeded;
}public intgetReenterLimit() {returnreenterLimit;
}public void setReenterLimit(intreenterLimit) {this.reenterLimit =reenterLimit;
}
}/*** Sync object for non-fair locks*/
static final class NonfairSync extendsSync {private static final long serialVersionUID = 7316153563782823691L;public NonfairSync(intreenterLimit) {super(reenterLimit);
}/*** Performs lock. Try immediate barge, backing up to normal
* acquire on failure.*/
final voidlock() {if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);
}protected final boolean tryAcquire(intacquires) {returnnonfairTryAcquire(acquires);
}
}/*** Sync object for fair locks*/
static final class FairSync extendsSync {private static final long serialVersionUID = -3000897897090466540L;public FairSync(intreenterLimit) {super(reenterLimit);
}final voidlock() {
acquire(1);
}/*** Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.*/
protected final boolean tryAcquire(intacquires) {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)
if (nextc >getReenterLimit()) // 这里是关键throw newMaximumLockCountExceededException(getReenterLimit());//throw new Error("Maximum lock count exceeded");
setState(nextc);return true;
}return false;
}
}public voidlock() {
sync.lock();
}public void lockInterruptibly() throwsInterruptedException {
sync.acquireInterruptibly(1);
}public booleantryLock() {return sync.nonfairTryAcquire(1);
}public boolean tryLock(longtimeout, TimeUnit unit)throwsInterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}public voidunlock() {
sync.release(1);
}publicCondition newCondition() {returnsync.newCondition();
}public intgetHoldCount() {returnsync.getHoldCount();
}public booleanisHeldByCurrentThread() {returnsync.isHeldExclusively();
}public booleanisLocked() {returnsync.isLocked();
}public final booleanisFair() {return sync instanceofFairSync;
}protectedThread getOwner() {returnsync.getOwner();
}public final booleanhasQueuedThreads() {returnsync.hasQueuedThreads();
}public final booleanhasQueuedThread(Thread thread) {returnsync.isQueued(thread);
}public final intgetQueueLength() {returnsync.getQueueLength();
}protected CollectiongetQueuedThreads() {returnsync.getQueuedThreads();
}public booleanhasWaiters(Condition condition) {if (condition == null)throw newNullPointerException();if (!(condition instanceofAbstractQueuedSynchronizer.ConditionObject))throw new IllegalArgumentException("not owner");returnsync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
}public intgetWaitQueueLength(Condition condition) {if (condition == null)throw newNullPointerException();if (!(condition instanceofAbstractQueuedSynchronizer.ConditionObject))throw new IllegalArgumentException("not owner");returnsync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
}protected CollectiongetWaitingThreads(Condition condition) {if (condition == null)throw newNullPointerException();if (!(condition instanceofAbstractQueuedSynchronizer.ConditionObject))throw new IllegalArgumentException("not owner");returnsync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
}publicString toString() {
Thread o=sync.getOwner();return super.toString() + ((o == null) ?
"[Unlocked]":"[Locked by thread " + o.getName() + "]");
}
}