📄 lockset.java
字号:
factory, this, control, waitingLock, wakeupReason); if (deadlockData == null) { // we don't have a deadlock deadlockWait = false; actualTimeout = timeout; startWaitTime = 0; willQuitWait = false; } else { willQuitWait = true; } } nextWaitingLock = control.getNextWaiter( waitingLock, willQuitWait, this); // If we were not woken by another then we have // timed out. Either deadlock out or timeout if (willQuitWait) { // Even if we deadlocked trying to get the lock, // still reget the latch so that client's need not // know latch was released. if (latch != null) { lockObject( compatabilitySpace, latch.getLockable(), latch.getQualifier(), C_LockFactory.WAIT_FOREVER, (Latch) null); } if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("DeadlockTrace")) { SanityManager.showTrace(new Throwable()); // The following dumps the lock table as it // exists at the time a timeout is about to // cause a deadlock exception to be thrown. lockDebug = DiagnosticUtil.toDiagString(waitingLock) + "\nGot deadlock/timeout, here's the table" + this.toDebugString(); } } if (deadlockTrace && (deadlockData == null)) { // if ending lock request due to lock timeout // want a copy of the LockTable and the time, // in case of deadlock deadlockData has the // info we need. currentTime = System.currentTimeMillis(); timeoutLockTable = factory.makeVirtualLockTable(); } } } // synchronized block // need to do this outside of the synchronized block as the // message text building (timeouts and deadlocks) may // involve getting locks to look up table names from // identifiers. if (willQuitWait) { if (SanityManager.DEBUG) { if (lockDebug != null) { String type = ((deadlockData != null) ? "deadlock:" : "timeout:"); SanityManager.DEBUG_PRINT( type, "wait on lockitem caused " + type + lockDebug); } } if (deadlockData == null) { // ending wait because of lock timeout. if (deadlockTrace) { // Turn ON derby.locks.deadlockTrace to build // the lockTable. throw Timeout.buildException( waitingLock, timeoutLockTable, currentTime); } else { StandardException se = StandardException.newException( SQLState.LOCK_TIMEOUT); throw se; } } else { // ending wait because of lock deadlock. throw Deadlock.buildException( factory, deadlockData); } } } finally { if (nextWaitingLock != null) { nextWaitingLock.wakeUp(Constants.WAITING_LOCK_GRANT); nextWaitingLock = null; } } if (actualTimeout != C_LockFactory.WAIT_FOREVER) { if (wakeupReason != Constants.WAITING_LOCK_IN_WAIT) earlyWakeupCount++; if (earlyWakeupCount > 5) { long now = System.currentTimeMillis(); if (startWaitTime != 0) { long sleepTime = now - startWaitTime; actualTimeout -= sleepTime; } startWaitTime = now; } } } // for(;;) } finally { if (deadlockTrace) { // I am out of the wait state, either I got my lock or I // am the one who is going to detect the deadlock, don't // need the stack trace anymore. lockTraces.remove(waitingLock); } } } /** Unlock an object, previously locked by lockObject(). If unlockCOunt is not zero then the lock will be unlocked that many times, otherwise the unlock count is taken from item. */ void unlock(Latch item, int unlockCount) { if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON(Constants.LOCK_TRACE)) { /* ** I don't like checking the trace flag twice, but SanityManager ** doesn't provide a way to get to the debug trace stream ** directly. */ SanityManager.DEBUG( Constants.LOCK_TRACE, "Release lock: " + DiagnosticUtil.toDiagString(item)); } } boolean tryGrant = false; ActiveLock nextGrant = null; synchronized (this) { Control control = getControl(item.getLockable()); if (SanityManager.DEBUG) { // only valid Lock's expected if (item.getLockable() == null) { SanityManager.THROWASSERT( "item.getLockable() = null." + "unlockCount " + unlockCount + "item = " + DiagnosticUtil.toDiagString(item)); } // only valid Lock's expected if (control == null) { SanityManager.THROWASSERT( "control = null." + "unlockCount " + unlockCount + "item = " + DiagnosticUtil.toDiagString(item)); } if (getControl(control.getLockable()) != control) { SanityManager.THROWASSERT( "unlock mismatched lock items " + getControl(control.getLockable()) + " " + control); } if ((unlockCount != 0) && (unlockCount > item.getCount())) SanityManager.THROWASSERT("unlockCount " + unlockCount + " larger than actual lock count " + item.getCount() + " item " + item); } tryGrant = control.unlock(item, unlockCount); item = null; boolean mayBeEmpty = true; if (tryGrant) { nextGrant = control.firstWaiter(); if (nextGrant != null) { mayBeEmpty = false; if (!nextGrant.setPotentiallyGranted()) nextGrant = null; } } if (mayBeEmpty) { if (control.isEmpty()) { // no-one granted, no-one waiting, remove lock control remove(control.getLockable()); } return; } } // synchronized (this) if (tryGrant && (nextGrant != null)) { nextGrant.wakeUp(Constants.WAITING_LOCK_GRANT); } } /* ** Non public methods *///EXCLUDE-START-lockdiag- void setDeadlockTrace(boolean val) { // set this without synchronization deadlockTrace = val; if (val && lockTraces == null) { lockTraces = new Hashtable(); } else if (!val && lockTraces != null) { lockTraces = null; } } //EXCLUDE-END-lockdiag- public String toDebugString() { if (SanityManager.DEBUG) { String str = new String(); int i = 0; for (Enumeration e = this.elements(); e.hasMoreElements(); i++) { str += "\n lock[" + i + "]: " + DiagnosticUtil.toDiagString(e.nextElement()); } return(str); } else { return(null); } }//EXCLUDE-START-lockdiag- /* * make a shallow clone of myself and my lock controls */ /* package */ synchronized LockSet shallowClone() { LockSet clone = new LockSet(factory); for (Enumeration e = keys(); e.hasMoreElements(); ) { Lockable lockable = (Lockable)e.nextElement(); Control control = getControl(lockable); clone.put(lockable, control.shallowClone()); } return clone; }//EXCLUDE-END-lockdiag- /* ** Support for anyoneBlocked(). These methods assume that caller ** is synchronized on this LockSet object. */ void oneMoreWaiter() { blockCount++; } void oneLessWaiter() { blockCount--; } boolean anyoneBlocked() { if (SanityManager.DEBUG) { SanityManager.ASSERT( blockCount >= 0, "blockCount should not be negative"); } // no synchronization needed because reads of ints are atomic return blockCount != 0; } public final Control getControl(Lockable ref) { return (Control) get(ref); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -