| Modifier and Type | Field and Description |
|---|---|
| private static final DeadLockComponent | |
| public static final ExplainDeadLockUtil |
| Access | Constructor and Description |
|---|---|
| private |
| Modifier and Type | Method and Description |
|---|---|
| protected List | Returns: return the dead lock explanation as a simple list that is easy to iterate over without going into infinite loops and where we get rid of the primal repeating thread of our recursion which is lacking metadata about the nature of the dead lock on the thread.The outcome of the explain dead lock algorithm. The last DTO on this data structure is lacking
metadata and we want to get rid of it. deadLockExplanation)When the last (repeating thread) of a dead lock is discovered and we start the unwinding of the recursion, the
first DTO we create is flagged with
|
| protected boolean | Returns: TRUE if we are aware of one or more resources that the current thread strives to acquire but cannot get false if we are clueless as to any desire for the thread.the dto that holds the state of the cocurrency manager for our dead lock detection algorithm concurrencyManagerStateDto, final Thread the thread we are trying to evaluate currentCandidateThreadPartOfTheDeadLock)This a helper sanity check. |
| protected DeadLockComponent | Returns: the DTO representing a component part of a dead lockthe thread that was participating in the dead lock as we went deeper in the recursion. nextThreadPartOfDeadLock, Thread the thread at the current depth that is part of the dead lock threadNotAbleToAccessResource, ConcurrencyManager this is a cache key that is not necessarily desired by the blocked thread, but which is recrusively
blocking the thread stuck in cacheKeyBlockingIsBuildObjectComplete)isBuildObjectcomplete logic. This is a bit complicated to
explain, but essentially when a thread cannot acquire write lock it sometimes can defer on the lock.
Later to finish object building the thread will be waiting to make sure that locks it deferred are
considered to be all finished. When deferred lock is not finished it could be cause much deeper some
other secondary object could not be built due to some cache key not accessible.. Therefore the
cacheKeyBlockingIsBuildObjectComplete might be quite deep and far away from the cache key our thread
had to defer... It is an element blocking our thread from finishing.Create a deadlock component for a thread known to be stuck trying to release deferred locks. |
| protected DeadLockComponent | Returns: the DTO representing a component part of a dead lockthe thread that was participating in the dead lock as we went deeper in the recursion. nextThreadPartOfDeadLock, Thread the thread at the current depth that is part of the dead lock threadNotAbleToAccessResource, ConcurrencyManager the cache key that the thread wanted to acquire for writing cacheKeyThreadWantsToAcquireButCannotGet)Dto component participating in a dead lock. |
| protected DeadLockComponent | Returns: the DTO representing a component part of a dead lockthe dto component of a dead lock that comes from a depper recursion expansion nextThreadPartOfDeadLock, Thread the thread at the current depth that is part of the dead lock threadNotAbleToAccessResource, ConcurrencyManager the cache key that the thread wanted to acquire for writing cacheKeyThreadWantsToAcquireButCannotGet)Create a dead lock dto component. |
| public List | Returns: A string that triesA clone we have assembled based on the concurrency manager and write lock manager state concurrencyManagerState)Given the concurrency manager state try to explain why we are facing a dead lock. |
| public static IsBuildObjectCompleteOutcome | isBuildObjectOnThreadComplete(final ConcurrencyManagerState
our representation of a cloned ste of the concurrency manager and write lock manager concurrencyManagerStateDto, Thread the current thread to explore which might have deferred locks. At level 1 of the recursion the thread
is certain to have deferred locks. thread, Map<Thread, Thread> this is an hash map holding the threads in the current recusion algorithm that have been expanded
already to avoid expanding more than once the same thread and going into an infinite dead lock. recursiveSet)This method is nothing more than copy paste code from the algorithm
|
| protected DeadLockComponent | Returns: NULL if no dead lock is found. a value if a deadlock is foundstate of the concurrency manager concurrencyManagerState, final int max allowed depth for recursion. recursionMaxDepth, final int the current recursion depth currentRecursionDepth, final Thread the current thread we are expanding in dpeth currentCandidateThreadPartOfTheDeadLock, List<Thread> the current thread of sets comrpising our dead lock expansion. threadPartOfCurrentDeadLockExpansion, Set<Thread> threads we have expanded in the past and gave no fruits threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager the cache key we know our current candidate wants and is not getting. cacheKeyThreadWantsToAcquireButCannotGet, boolean a flag that tells us if our current candidate thread is strugling to acquire a lock with the purpose
of writing or just for reading. currentThreadWantsToAcquireForWriting)Try to expand the current thread from the perspective that it wants a cache key that may be own for writing by a competitor thread. |
| protected DeadLockComponent | Returns: NULL if no dead lock is found. a value if a deadlock is foundstate of the concurrency manager concurrencyManagerState, final int max allowed depth for recursion. recursionMaxDepth, final int the current recursion depth currentRecursionDepth, final Thread the current thread we are expanding in dpeth currentCandidateThreadPartOfTheDeadLock, List<Thread> the current thread of sets comrpising our dead lock expansion. threadPartOfCurrentDeadLockExpansion, Set<Thread> threads we have expanded in the past and gave no fruits threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager the cache key we know our current candidate wants and is not getting. cacheKeyThreadWantsToAcquireButCannotGet, boolean a flag that tells us if our current candidate thread is strugling to acquire a lock with the purpose
of writing or just for reading. currentThreadWantsToAcquireForWriting)Try to expand the current thread from the perspective that it wants a cache key that may be own for writing by a competitor thread. |
| protected DeadLockComponent | Returns: NULL, if we reach a dead end without a dead lock. If a non result is returned means that the current thread is part of a dead lock identified..how deep do we want our brute force algorithm to go. Probably 6 threads is good enough to discover
most dead locks. Max depth should be set to number of threads we believe can logically form a dead
lock + 1. recursionMaxDepth, final int how deep we are in the recursion currentRecursionDepth, final Thread the current thread we want to expand currentCandidateThreadPartOfTheDeadLock, List<Thread> a small optimization. If in the past we xplored expanding Thread A and now we are via a different
routing trying to find a dead lock via thread A again we can immediately ignore expanding the thread. threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain)The algorithm expands the current thread in depth. |
| protected DeadLockComponent | Returns: NULL, if we reach a dead end without a dead lock. If a non result is returned means that the current thread is part of a dead lock identified..the max depth the recursion is allowed to reach before deciding it is pointless to go any further. Max
depth should be set to number of threads we believe can logically form a dead lock + 1. recursionMaxDepth, final int how deep we are in the recursion currentRecursionDepth, final Thread the current thread we want to expand currentCandidateThreadPartOfTheDeadLock, List<Thread> a small optimization. If in the past we xplored expanding Thread A and now we are via a different
routing trying to find a dead lock via thread A again we can immediately ignore expanding the thread. threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain)Precondition the logic of |
| protected DeadLockComponent | Returns: NULL if we get nowhere trying to find the dead lock otherwise a DTO explaining this thread and the successor threads that make the dead lockstate of concurrency manager concurrencyManagerStateDto, final int how deep the recursion can go recursionMaxDepth, final int the current depeth currentRecursionDepth, final Thread the current thread we are expanding and that may be involved in explaning a dead lock currentCandidateThreadPartOfTheDeadLock, List<Thread> the predecessor threads that are part of a dead lock expansion we are searching threadPartOfCurrentDeadLockExpansion, Set<Thread> these are threads we already expanded at depth 1 and we know they took us nowhere. We just assume
expanding these a second time is a waste of time. threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager this is the cache key we have identified as making a our candidate thread stuck and we want to explore
who is owning this cache key cacheKeyCurrentThreadWantsForWritingButCannotGet)We are looking at thread that we know has registered itself as wanting to acquire a write lock and not managing to make progress getting the write lock. |
| protected DeadLockComponent | recursiveExplainPossibleDeadLockStep03Scenario01CurrentWriterVsOtherWritersWriter(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet)
Expand the possibility of the current thread wanting to acquire for writing what some other already has acquired for writing. |
| protected DeadLockComponent | Returns: NULL if dead lock not discovered. Otherwise dead lock component justifying the deadlock.Expand the recursion exploring the possibility that the reason the current thread cannot acquire the cache key is because there are readers on the cache key. |
| protected DeadLockComponent | Returns: NULL if looking at the active thread of the wanted cache key does not bare any fruits, otherwise the dead lock component object are returned.In scenario 3 is when we start considering the possbility our data for detecting the dead lock is not ok or the cache is corrupted. |
| protected DeadLockComponent | Returns: NULL if we are able to explain a dead lock via expanding this the current candidate thread Otherwiser a DTO component that explains the the dad lockWhen a thead cannot move forward due to having deferred cache keys, it means that the thread could not go as deep as it wanted during object building and hda to defer making some parts of the object. |
| protected DeadLockComponent | recursiveExplainPossibleDeadLockStep05ExpandBasedOnCacheKeyWantedForReading(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForReadingButCannotGet)
In this case have a thread that wants to acquire for reading a cache key but it does not manage to acquire it because the cache key is being owned by somebody else. |
| protected DeadLockComponent | recursiveExplainPossibleDeadLockStep05Scenario01CurrentReaderVsOtherWriters(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet)
Expand the possibility of the current thread wanting to acquire for writing what some other already has acquired for writing. |
| protected DeadLockComponent | recursiveExplainPossibleDeadLockStep05Scenario02CurrentReaderVsCacheKeyActiveThread(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet)
Same as
|
| DEAD_LOCK_NOT_FOUND | back to summary |
|---|---|
| private static final DeadLockComponent DEAD_LOCK_NOT_FOUND | |
| SINGLETON | back to summary |
|---|---|
| public static final ExplainDeadLockUtil SINGLETON | |
| ExplainDeadLockUtil | back to summary |
|---|---|
| private ExplainDeadLockUtil() | |
| createListExplainingDeadLock | back to summary |
|---|---|
| protected List When the last (repeating thread) of a dead lock is discovered and we start the unwinding of the recursion, the
first DTO we create is flagged with
| |
| currentThreadIsKnownToBeWaitingForAnyResource | back to summary |
|---|---|
| protected boolean currentThreadIsKnownToBeWaitingForAnyResource(final ConcurrencyManagerState concurrencyManagerStateDto, final Thread currentCandidateThreadPartOfTheDeadLock) This a helper sanity check. Whenever we expand a threa we expect the thread must be starved fro some resource.
| |
| deadLockFoundCreateConcurrencyManagerStateDeferredThreadCouldNotAcquireWriteLock | back to summary |
|---|---|
| protected DeadLockComponent deadLockFoundCreateConcurrencyManagerStateDeferredThreadCouldNotAcquireWriteLock(final DeadLockComponent nextThreadPartOfDeadLock, Thread threadNotAbleToAccessResource, ConcurrencyManager cacheKeyBlockingIsBuildObjectComplete) Create a deadlock component for a thread known to be stuck trying to release deferred locks.
| |
| deadLockFoundCreateConcurrencyManagerStateReaderThreadCouldNotAcquireWriteLock | back to summary |
|---|---|
| protected DeadLockComponent deadLockFoundCreateConcurrencyManagerStateReaderThreadCouldNotAcquireWriteLock(final DeadLockComponent nextThreadPartOfDeadLock, Thread threadNotAbleToAccessResource, ConcurrencyManager cacheKeyThreadWantsToAcquireButCannotGet) Dto component participating in a dead lock.
| |
| deadLockFoundCreateConcurrencyManagerStateWriterThreadCouldNotAcquireWriteLock | back to summary |
|---|---|
| protected DeadLockComponent deadLockFoundCreateConcurrencyManagerStateWriterThreadCouldNotAcquireWriteLock(final DeadLockComponent nextThreadPartOfDeadLock, Thread threadNotAbleToAccessResource, ConcurrencyManager cacheKeyThreadWantsToAcquireButCannotGet) Create a dead lock dto component.
| |
| explainPossibleDeadLockStartRecursion | back to summary |
|---|---|
| public List Given the concurrency manager state try to explain why we are facing a dead lock.
| |
| isBuildObjectOnThreadComplete | back to summary |
|---|---|
| public static IsBuildObjectCompleteOutcome isBuildObjectOnThreadComplete(final ConcurrencyManagerState concurrencyManagerStateDto, Thread thread, Map<Thread, Thread> recursiveSet) This method is nothing more than copy paste code from the algorithm
| |
| recursiveExpansionCurrentThreadBeingBlockedByActiveThreadOnCacheKey | back to summary |
|---|---|
| protected DeadLockComponent recursiveExpansionCurrentThreadBeingBlockedByActiveThreadOnCacheKey(final ConcurrencyManagerState concurrencyManagerState, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyThreadWantsToAcquireButCannotGet, boolean currentThreadWantsToAcquireForWriting) Try to expand the current thread from the perspective that it wants a cache key that may be own for writing by a competitor thread.
| |
| recursiveExpansionCurrentThreadBeingBlockedByActiveWriters | back to summary |
|---|---|
| protected DeadLockComponent recursiveExpansionCurrentThreadBeingBlockedByActiveWriters(final ConcurrencyManagerState concurrencyManagerState, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyThreadWantsToAcquireButCannotGet, boolean currentThreadWantsToAcquireForWriting) Try to expand the current thread from the perspective that it wants a cache key that may be own for writing by a competitor thread.
| |
| recursiveExplainPossibleDeadLockStep01 | back to summary |
|---|---|
| protected DeadLockComponent recursiveExplainPossibleDeadLockStep01(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain) The algorithm expands the current thread in depth. If the current thread is already part of the threadPartOfCurrentDeadLockExpansion then we have found our dead lock. If we return null, we are empty handed ... we cannot explain the dad lock.
| |
| recursiveExplainPossibleDeadLockStep02 | back to summary |
|---|---|
| protected DeadLockComponent recursiveExplainPossibleDeadLockStep02(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain) Precondition the logic of
| |
| recursiveExplainPossibleDeadLockStep03ExpandBasedOnCacheKeyWantedForWriting | back to summary |
|---|---|
| protected DeadLockComponent recursiveExplainPossibleDeadLockStep03ExpandBasedOnCacheKeyWantedForWriting(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet) We are looking at thread that we know has registered itself as wanting to acquire a write lock and not managing
to make progress getting the write lock. We need to have a look at the
| |
| recursiveExplainPossibleDeadLockStep03Scenario01CurrentWriterVsOtherWritersWriter | back to summary |
|---|---|
| protected DeadLockComponent recursiveExplainPossibleDeadLockStep03Scenario01CurrentWriterVsOtherWritersWriter(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet) Expand the possibility of the current thread wanting to acquire for writing what some other already has acquired for writing. | |
| recursiveExplainPossibleDeadLockStep03Scenario02CurrentWriterVsOtherReader | back to summary |
|---|---|
| protected DeadLockComponent recursiveExplainPossibleDeadLockStep03Scenario02CurrentWriterVsOtherReader(final ConcurrencyManagerState concurrencyManagerState, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet) Expand the recursion exploring the possibility that the reason the current thread cannot acquire the cache key is because there are readers on the cache key.
| |
| recursiveExplainPossibleDeadLockStep03Scenario03CurrentWriterVsCacheKeyActiveThread | back to summary |
|---|---|
| protected DeadLockComponent recursiveExplainPossibleDeadLockStep03Scenario03CurrentWriterVsCacheKeyActiveThread(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet) In scenario 3 is when we start considering the possbility our data for detecting the dead lock is not ok or the cache is corrupted. We consider quite simply the thread that is flagged as the active thread on the cache key since this is the thread owning the cache key. However if we call for this scenario it means we did not find in our DTO any reader or writer owning the thread. So if indeed the cache key our thread is trying to acquire has an active thread and we do not know what this thread is currently doing - since the thread should either be in our basket of writers or in our basket of readers, we are stuck.
| |
| recursiveExplainPossibleDeadLockStep04ExpandBasedOnThreadStuckOnReleaseDeferredLocks | back to summary |
|---|---|
| protected DeadLockComponent recursiveExplainPossibleDeadLockStep04ExpandBasedOnThreadStuckOnReleaseDeferredLocks(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain) When a thead cannot move forward due to having deferred cache keys, it means that the thread could not go as deep as it wanted during object building and hda to defer making some parts of the object. The thread is stuck because the parts of the object it could not build are apparently not finished either.
| |
| recursiveExplainPossibleDeadLockStep05ExpandBasedOnCacheKeyWantedForReading | back to summary |
|---|---|
| protected DeadLockComponent recursiveExplainPossibleDeadLockStep05ExpandBasedOnCacheKeyWantedForReading(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForReadingButCannotGet) In this case have a thread that wants to acquire for reading a cache key but it does not manage to acquire it because the cache key is being owned by somebody else. So we need to see what the writer of this cache key is doing. | |
| recursiveExplainPossibleDeadLockStep05Scenario01CurrentReaderVsOtherWriters | back to summary |
|---|---|
| protected DeadLockComponent recursiveExplainPossibleDeadLockStep05Scenario01CurrentReaderVsOtherWriters(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet) Expand the possibility of the current thread wanting to acquire for writing what some other already has acquired for writing. | |
| recursiveExplainPossibleDeadLockStep05Scenario02CurrentReaderVsCacheKeyActiveThread | back to summary |
|---|---|
| protected DeadLockComponent recursiveExplainPossibleDeadLockStep05Scenario02CurrentReaderVsCacheKeyActiveThread(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet) Same as
| |