• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Order of releasing locks

 
oli renard
Greenhorn
Posts: 28
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello everyone,
As part of my assignment (B&S 2.1.1), I have written to lock managers: a ReadWriteLockManager and a RecordLockManager. The RecordLockManager is obviously used for locking/unlocking records in the database. The ReadWriteLockManager is to manage read and write access to the database. All reads are concurrent in that lock manager, but for writes (such as adding a record to the database), then all reads are put on hold until the write is finished and writes are sequential.
My intention was to use both these managers for update and delete, but my question is: what order should the locks by released in? Is is in the reverse order to the order they were acquired or is it in the same order? To put this into context, should it be solution 1 (reverse order) or solution 2 (same order):

I know that adding records is not part of the GUI interface, but I have provided an implementation for it. So, if in the future, such implementation is needed, it is very easy to add it without impacting the rest of the code. The reason why I am using getReadLock() above is because the getWriteLock() in the ReadWriteLockManager is only used to add records to the database. Please do not let this distract you from my original question.
All help is greatly appreciated.
Oli
 
Nathaniel Stoddard
Ranch Hand
Posts: 1258
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I didn't spend more than a few seconds looking at your post, so forgive me if this is a stupid question ... but why are you differentiating between read locks and write locks? Maybe the assignments have changed in a while, but back in my day (URLyBird), we just locked it when it needed to be locked, and that was that.
 
oli renard
Greenhorn
Posts: 28
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nathaniel, I do not think there is such a thing as a stupid question, so there is no need to apologise. In fact, I should apologise for not explaining things well enough in the first place. The ReadWriteLockManager is simply there to ensure that no data is read from the database while a record is being added to the database. That is all. All I wanted to be sure about is the order in which the locks were being released.
Thank you
 
Nathaniel Stoddard
Ranch Hand
Posts: 1258
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ah -- now this is making sense In fact, when I did my assignment, I used one locking manager and everything went through it (even locks on records that didn't exist at the moment). Of course, I didn't really expect anybody to read a value that didn't exist. BUT, since there was some little tag in the record that indicated whether a record was valid, I just made sure that the record being written had it's values set correctly, and then marked the record as valid.
So, if a thread accessed the record, it would either throw a RecordNotFoundException (record was not yet marked as valid), or would successfully retrieve the record.
I'm still dizzy looking at your code -- are you making sure that NO reads occur while a record is being updated or inserted? I assume that readWriteLockManager.getReadLock() will block until the current thread successfully owns the monitor allowing all reads on the database.
In that case, I don't think it matters which one you do.
If you release the read lock first, any new read operations will not care since the next operation will release the lock (it's in a valid state already). If the next operation is another update/insert, it doesn't matter for the same reasons.
If you release the record lock first, any new read operations will block until you release the read lock anyways - so there's no synchronization issue there. If the next operation (by a separate thread) is another insert/update, then it's going to want to get the read lock, too, which won't be possible until the current thread releases it.
So, assuming that the read lock method blocks on some monitor, you're all set. Maybe. Where does that leave us?
 
oli renard
Greenhorn
Posts: 28
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello again Nathaniel. Sorry if my code makes you dizzy, this is definitely not intentional ;-). Just to confirm:
are you making sure that NO reads occur while a record is being updated or inserted?

The getReadLock() method ensures that all reads can be perfomed concurrently. Hence, an update can take place too since it does not change the size of the database. If a new record is being inserted, then I would need to invoke the getWriteLock() method.
I guessed I have completely confused you and I apologise. I guess I am trying too hard and should try to get something more simple in place. The fact that you only had one manager and I have 2 is already a cause for concern as far as my code is concerned.
Looking at the other post (Design review and thread-safety - and thank you very much for your feedback there too, BTW), I think that I should simply get a RecordLockManager and ensure that my Data class is thread-safe. However, if I do not implement a ReadWriteLockManager, I still need to ensure that no-one is inserting a new record in the database when I read the database otherwise there could be some problems. How did you approach this problem? The interface that I have has an add() method. However, the functionality it provides is not supposed to be available to the client. The same goes for the delete() method. Should I still provide an implementation for these? My intention was to have this in the Data class:

and simply synchronize on it in all of the public methods in the Data class so that no-one could read and insert a record at the same time. The downside is that reads would not be concurrent, but rather sequential, which is what I am trying to avoid. May I ask how you overcame this if you faced the same issue? If you did face this same issue, how would you suggest I proceed to overcome this?
Thank you very much indeed.
(BTW, I need to get some sleep as I'll have to get up in about 6 hours to go to work, so I'll catch up with you tomorrow. Thank you ever so much for all your feedback and help on this, Nathaniel. It is immensely appreciated, believe me.)
Oli
 
George Marinkovich
Ranch Hand
Posts: 619
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Oli,
Long time, no post... Welcome back!
You're asking about how to go about nesting locks for this project, so first I've got to say:

nested locks can lead to deadlock and they probably aren't needed to solve the problems presented in the assignment.

Ok, now that we've got that out of the way. (You knew someone was going to say that, didn't you?) If you have three locks that you have to acquire in order to do something, then to avoid deadlock these locks should always be acquired in the same order. The locks should always be released in the reverse order. For example:

In terms of your example, that's solution 1 (reverse order).
Before you continue with your "dance with deadlock" you should check out the discussion here: Topic: Does nest locks really bad?
[ March 09, 2004: Message edited by: George Marinkovich ]
 
oli renard
Greenhorn
Posts: 28
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you George. Indeed, long time no post, but I am obviously remedying this (with 2 different posts in a single day!).
Thank you for your feedback and I have to say that I do share your concern regarding nested locks. My intention really was to do this for updating a record in the business tier:

In my Data class, the update method itself would read as follows:

So I suppose that I am nesting locks. I really cannot see how this can be avoided. I do not have a static reference to a RandomAccessFile in my Data class. Each method uses its own. If I do synchronize on a static reference to an Object for all database access, then that means that at any point in time there can only ever be 1 IO operation taking place. While I do understand why one would want to go down this route, I just think that reads should be concurrent and this is what my ReadWriteLockManager enables me to do while ensuring that any writes does not interfere with any read operation. The real concern that I have is regarding the add() method because I want to avoid reading the database while someone is adding a record to it. I know that the add() method is not part of the GUI, but I still have to provide an implementation for it.
If you have any other ideas as to how such a nested lock can be avoided, please let me know as I cannot see any other solution at present.
Regards
Oli
 
Consider Paul's rocket mass heater.
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic