Ranchers,
I have the following interface, which would be similar to that of many other assignments/versions:
The interface implies a usage sequence lock->update/delete->unlock, which is reasonable.
The interface locking calls also imply that the record number of the record to be locked must be known by the interface user. This can only be the case if the create methods is called, or the find method is called and provides record numbers as part of the returned data.
To illustrate, the interface user could otherwise be guessing record numbers from LONG.MINVALUE to LONG.MAXVALUE and poke around in a black hole. However, this would be rather inefficient database use. For example, in a data file with only one valid record left (e.g. number 284938), we could poke around forever with not much success at all.
Now the concurrency issue: The interface implies that creating records has no concurrency issues, since no lock cookie/record number can be passed as an argument. The interface also does not provide any calls to determine record numbers (=file areas) available for record creation.
A concurrency problem occurs if a locking strategy is implemented which allows for concurrent record manipulation (deletes, updates) on different records as:
within the lock method, each thread can obtain a reference to a record specific lock object (being/extending ReentrantLock) in an unsynchronized manner. Note: the record is not yet locked at this stage, which facilitates that threads are not waiting for unrelated record locks to be released.Upon calling the/a lock method on the lock object, all other treads have to wait for the lock of that particular record only to be released. An example scenario would be:
Client Thread T1 enters create, and starts to write the record bytes (e.g. immediately after the last record in the file), without that file section being locked.Client Thread T2 enters create, and also starts to create a record immediately after the the last record, in the unlocked file section. It overwrites/interferes with whatever T1 does. I found there was only one solution:
1. synchronize the create method altogether. Only one thread can create at any one time in an unlocked file section. This works particularly well if deleted records are not reused (i.e. all threads create a record immediately after the last completely written record). It mandates though that only the create method will ever be accessing that unlocked section.
Implicit locking within create somewhat breaks the clean lock->recordmanipulation->unlock sequence stipulated by the interface. Also, it raises a problem with ensuring two create calls are not overwriting each other by:
T1 and T2 obtaining a lock reference for an identical file area (say free record at end of file to be record 32)T1 locking that section, writing data, unlockingT2 locking section that now holds data, overwriting, unlocking Anyone came across this issue? Any thoughts?
ChrisBe
[ September 26, 2007: Message edited by: Chris Be ]