Hi,
Here is a rough overview with more specifics.
The lock manager is called Guardian.
-----------------------------------
* The Guardian methods are rarely synchronized as it is multi-threaded.
However, when it does work, it locks the guard object which keeps track of
which records are currently locked. There are other structures, such as to
keep track of deleted record numbers. All these structures are used together
and are synchronized on guard whenever any work is done.
* Some Guardian methods call into DataCore class methods, such as to see if a
record number exists within the file.
Thus, the locking order is always the following:
lock guard, then call a method in DataCore which locks on dataCore instance.
dataCore instance
-----------------
The reader and writer with all its methods synchronized is called
DataCore (except that the create() methods are the only methods which are not
synchronized).
The create() method will use the lock manager which in turn will call back into
a synchronized method of dataCore, which, if not handled correctly, will result
in dead-lock.
The create() method needs to lock a record, whether a previously deleted record
or a record at the end of the file, prior to writing new information to it and
effectively creating this record.
So, when a record is created, and the dataCore.create() method is called,
it first locks down all data structures associated with the lock manager.
Therefore, no new threads can query the lock manager nor request that any
record be locked.
Eventually, any threads that are reading and writing using any of dataCore's
synchronized methods will finish, and the create() method will get the lock
on "this" (which is the instance of dataCore).
The lock manager, Guardian, can then be safely used, including its abilities to
call back into synchronized methods of dataCore.
To answer your question: what happens to concurrency if the inner lock is not
available? I'd say not much, if the lock is not available, the dataCore object
is already busy reading, writing, or both.
The dataCore methods are not yet optimized. I have my
JUnit code working, so
that subsequent optimization to heighten concurrency can occur easily in the
near future. So, in the future, dataCore's complete methods will not be
synchronized, only the critical sections within them will be synchronized on
"this". The same applies to the createContinued() method, its critical section
will be synchronized inside the code, using the the same, dual locks:
guard and this.
Another related question I have is what other design choice exists for creating
a record?
One idea I thought of while writing this out this morning, is that I could
create a new thread to carry out the create operation; this thread would be
sent to use a different object, which then, in turn, would use the lock manager
and then create a new record; then this thread would have to use a notify
pattern to tell the original thread the results of the operation. But, I think
my design as written is simpler to understand, and I think it does not harm
concurrency. (but, of course, if I was certain, then I probably would not be
posting this type of question).
Thanks,
Javini Javono