I was just reviewing my server side locking for my URLyBird assignment by comparing what I had done with the approach in Andrew's book. The main question I have is regarding the persistDVD method in Andrew's example application (which is similar to my createRecord/updateRecord methods), where I think there may be a potential threading issue. I have tried to overcome this in my code, but it does make my code somewhat complex/possibly prone to deadlock by using nested synchronized blocks. Here is an outline of Andrew's code I am talking about
If you look at the comment above "//Daniel - MY QUESTION RELATES TO HERE" I think that at this point if another thread cut in and wanted to read the record that has just be created it would look in the recordNumbers collection (which is allowable, as at this point the original thread has released the lock), determine the offset at which to begin reading, synchronize on the database and then read the data. However, as the original thread hasn't written anything yet the new thread would see the record as empty?
The main question I am asking is that wouldn't it make sense to keep the recordNumbersLock.writeLock() locked until after the database has updated, removing the possibility of the scenario described. Doing this does mean that synchronised blocks are nested (hich I believe is a bad thing?) My code is something like this:
As you can see I don't exit the synchronised block until the database write is complete.
Does anyone have any comments on this? am I creating potential for deadlock by nesting synchronised blocks? or maybe I am missing something really obvious with Andrew's original code.
The main question I am asking is that wouldn't it make sense to keep the recordNumbersLock.writeLock() locked until after the database has updated,
You are correct. How about 2 threads each creating a new record. This could end up in both records getting the same offset, and one of both being overwritten in the database.
General remark on your updateRecord method: try to implement a separate classes for 1. file access, and 2. for functionial locking of a record by the clients (as in Andrews book).
posted 14 years ago
Thanks for your comments - I asked the question a couple of weeks ago and no-one responded. When I saw your question posted I was happy that someone else had spotted the same problem.
I've coded around this issue now, and as you have suggested, seperated my locking and DB access (I've actually got a seperate thread on just this point).
In order to avoid threads getting the same offset I have incremented the currentRecNumber in my createRecord() method so that every call to this method gets a unique number, and then in the read method I synchronize on the RAF and check that the position of the record we are trying to read is not beyond the length of the database (which could be the case if a thread cuts in between a new recNo being assigned, but not yet written to the DB).
"General remark on your updateRecord method: try to implement a separate classes for 1. file access, and 2. for functionial locking of a record by the clients (as in Andrews book)."
I don't know how to implement seperate classes for file access and functional locking. If the function of "update" is implemented in file access, how could the record cookie verifed? Since the cookie map variables should be in locking class and not in file access class?
Could you give me some suggestion?
posted 14 years ago
It is possible - I would recommend doing some research on the "Facade" Design pattern. Two books, "SCJD For J2SE" By Andrew Monkhouse and "Head First Deign Patterns" by Kathy Sierra and Bert Bates are excellence resources for the exam, and will provide all the information you need about design patterns that will be useful in your project.
You can also look at this thread to see a discussion in which I ask how to seperate out the DB and locking code.