Originally posted by Mark Smyth:
Hi guys,
First off sorry about the long post and also for starting yet another locking thread. I would like to ask your opinions on my locking strategy of which I have two different versions. Before I start I must point out record number is a place number in the file including deleted records (Which are never returned). So a findAll() might return 1, 4,5,8,9.as active records for example.
The first version synchronizes on a
HashMap but the notifyAll() on this in the unlocking method wakes up all threads including those not interested in the record that has just been unlocked. The consumes little enough space as only currently locked methods are stored in this
HashMap. The code looks like this
The second maintains an
ArrayList of lock objects for both deleted and active records, but of course only active records will actually lock. This is much less scalable (bad always) but guarantees that only interested threads are woken (good for SCJD).
I have to admit Mark, I'm lost here. Here you say that only active records will lock and that's exactly what is needed. But what I don't understand is - what is the difference in this and the above one where you are synchronizing the lockedRecords
HashMap. In the lockedRecords also only active records will be added right? So on what terms are you differentiating this from the above approach?
This
ArrayList object is only ever altered by int create() (only if a record is appended to end of file) and an initialiselocks() method in the Data object constructor.
Here, what do you mean by initializing locks? Before the first thread access Data object or when the first thread access Data, why are you populating the initializelocks? What are you storing in them? It seems that you are storing all the records present, both active and deleted from DB. Am I right?
In these methods I synchronize on the container.
As it is only modified by these two methods I believe the following code to be thread safe (Synchronization in locking methods is done on the specific record element get(recNo) only). Seemed ok in tests anyway, is more efficient but certainly less scalable.
I couldn�t think of a way to do this with a hashmap as you cannot synchronize on a null object (If the record is not locked) and besides you would have to synchronize on the
HashMap in the lock methods as it is being altered. Currently the hashmap impl is commented out but I think that I would be more comfortable about submitting the it than this one.
Off the point somewhat, ironically I left out an almost identical caching mechanism for pretty much the same reason, except in that case I didn�t really know how to achieve a better result. But I am now thinking if it�s a bad idea for a cache, it�s a bad idea for locks.
Here is my second lock method
This is the lock initialisation method called in Data(). Instance variable numRecords and numFields used in body.
private void initaliseLocks(
RandomAccessFile file) throws IOException{
}
Same as above. I do not understand what you are doing in this method. Are you populating all the active and deleted records in lockedRecords
HashMap before the very first thread access the DB?
And this is the bones of LockObject stored in the
ArrayList just contains a Boolean and a String for the name, simple implementation omitted.
Also perhaps as the second method is a little more complex perhaps it goes against the simplicity before efficiency spirit of the assignment (In my spec anyway).
I would really appreciate any comments or suggestions on the pros and cons of each approach.