To achieve its requirements,
DefaultComponentKeeper synchronizes on 3 different maps
nascentComponents) and the values contained within
creationLocks referred to as
creation lock objects. When the
uses nested synchronization, it synchronizes on a creation lock
object first, then either
nascentComponents. Synchronization is never nested more than
2 deep. Neither
creationLocks nor creation lock objects
are synchronized within another synchronization block.
A lock on
componentMap is required any time a request is made
to get, add, or remove a component from
componentMap. The lock
is also required when
destroyAllComponents is called for the
duration of the call. This ensures that once
starts, no other requests are serviced until the the call ends.
A lock on
creationLocks is required any time a request is made
to get a component lock. Adds are implicit within gets and removes are
not allowed. A creation lock is only required when a component that
does not yet exist is requestes.
For each Component created, there is one creation lock object. This object
is created upon the first request for the Component. It is then used
synchronized during component creation
to ensure that only one thread creates a component.
nascentComponents is a temporary place to store components
while they are having their dependancies resolved. This is how circular
dependancies are resolved. Synchronization on
is required when components are retrieved, added, or removed. These
operations are only done during component creation.
- All gets from
componentMap happen one at a time. This means
fetchComponent method can only serve one component at
a time where the components requested already exist. Note that component
creations do not happen within this lock so creations do not affect gets.
fetchNewComponent requests must go through the same critical
section of code to get a creation lock object.
While one thread is getting a creation lock object,
no other thread can get one. This is also
true when components are retrieved, added, or removed from
nascentComponents. Both of these synchronizations are
for the span of a Map manipulation. This means that
fetchNewComponent calls interfere with each other, but do
not block each other (unless they synchronize on the same component
lock, i.e. are fetching the same component).