Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

NX: Databases Synchronization

 
Mark Smyth
Ranch Hand
Posts: 288
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I got the URLyBird assignment a few days ago and so far I have made a start on the assignment. I have a fair idea that I am going to use a HashSet for the purposes of locking and put a facade in front of data.java so that will be my only user of the DB.
My question is related to my file object
RandomAccessFile file=new RandomAccessFile(FILE_NAME, "rw");
In my class I use this file object in every access method. Obviously I dont want ny thread doing a file.seek() while another is reading and writing. Because of this I have ended up with alot of code like so
synchronized(file){
.....
}
This seems to somewhat defeat the purposes of the file locking and multiple threads cannot even read concurrently. What is the best solution to this problem? I was thinking of perhaps opening the file in each major method, creating a local file object and passing this to other helper methods as nescessary.This seems like an amaturish approach though. Can you have multiple pointers to the same file? I was thinking that a caching system while it might relieve this problem, might be overkill for such a small scale system Translation: Too lazy to put it in . Anyone got any thoughts??
 
Andrew Monkhouse
author and jackaroo
Marshal Commander
Pie
Posts: 12014
220
C++ Firefox Browser IntelliJ IDE Java Mac Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Mark,
This seems to somewhat defeat the purposes of the file locking and multiple threads cannot even read concurrently.

Not at all. The file synchronization and the logical locking of records have different functions.
As you noted - you need to synchronize your code around your file access so that you can ensure that the call to seek and the call to read or write are treated as an atomic operation.
However you also have a totally different problem: what happens when two clients try to update a record simultaneously? Your file level synchronization is not going to help you there:
  • client A does "update" on record 5
  • Client B does "update" on record 5


  • (where "update" is defined as a synchronized block {containing the calls to seek and write})
    Both clients think that they have locked the record!
    So you are probably going to want to verify that the record is still available just before booking the record:
  • client A does booking on record 5
  • Client B attempts to do booking on record 5 and throws an exception


  • (where "booking" is defined as a synchronized block {containing the calls to seek and read and then some logic to verify that the record is available, followed by a call to seek and write})
    But if you do that, then you have two problems:
  • You have synchronized far more code than you really need (you always want to have the smallest possible amount of code synchronized, otherwise you will be reducing performance)
  • Your code is synchronized in the wrong place - it is synchronized at your booking level, not at the actual reading / writing level.


  • Both problems can be overcome if you have logical record locking:
  • client A gets lock on record 5
  • client B attempts to get lock on record 5 - blocks
  • client A does read and verify and update on record 5
  • client A releases lock on record 5
  • client B gets lock on record 5
  • client B does read and verify and throws exception (releasing lock on the way)


  • (where "read" is defined as a synchronized block {containing the calls to seek and read} and "verify" is unsynchronized code and "update" is a synchronized block {containing the calls to seek and write})
    See how the lock methods work at a totally different level?
    By the way - I have not mentioned what the synchronized blocks synchronize on - you may find that having two diferent mutexes may work well for you. I have also left this at a fairly high level - I assume you can work from there.
    Regards, Andrew
     
    Derek Canaan
    Ranch Hand
    Posts: 64
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi Andrew,
    you may find that having two diferent mutexes may work well for you.
    Seek your advice on the use of notify/notifyAll on these mutexes:

    1. Is it necessary to have an explicit notify/notifyAll at the end of each synch block? I remembered one of your posts mentioned that the JVM will implicitly notify all threads waiting for these mutexes once the thread holding the mutex exits the synch block.
    2. If the above is true, under what circumstances should we use notify/notifyAll explicitly. Is it just for "good manners" that we notify others when we wre done with the mutex?
    thanks,
    derek
     
    Mark Smyth
    Ranch Hand
    Posts: 288
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Cheers Andrew,
    Decided on a Hashmap for the record locking. Will look something like this

    This will work as long as a client is only allowed lock a record over one network call as an atomic lock/process/unlock operation, not over multiple network method calls.
    Will have to tidy up my read/write code though to make it better. Thanks for the advice.
    [Andrew: removed some of the code - we don't allow code to be posted for the complete solution to a section of the assignment]
    [ February 06, 2004: Message edited by: Andrew Monkhouse ]
     
    • Post Reply
    • Bookmark Topic Watch Topic
    • New Topic