The Carbon Java Framework  

The Carbon Core Component Subsytem

Synchronization and Lock Ordering

Author: Doug Voet (dvoet at sapient.com)
Version: $Revision: 1.2 $($Author: dvoet $ / $Date: 2003/04/09 15:05:09 $)
Created: January 2002

Introduction

This technote describes how the DefaultComponentKeeper is synchronized and in what order locks are requested. Having a clearly defined ordering of locks is crucial for preventing deadlock situations.

Synchronization and Lock Ordering

To achieve its requirements, the DefaultComponentKeeper synchronizes on 3 different maps (componentMap, creationLocks and nascentComponents) and the values contained within creationLocks referred to as creation lock objects. When the DefaultComponentKeeper uses nested synchronization, it synchronizes on a creation lock object first, then either componentMap or 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 destroyAllComponents 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 nascentComponents is required when components are retrieved, added, or removed. These operations are only done during component creation.

Implications of Synchronization

  • All gets from componentMap happen one at a time. This means that the 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.
  • All 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).

Copyright © 2001-2003, Sapient Corporation