aspose file tools*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes NX: RandomAccessFile synchronization and record locking Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "NX: RandomAccessFile synchronization and record locking" Watch "NX: RandomAccessFile synchronization and record locking" New topic
Author

NX: RandomAccessFile synchronization and record locking

Mark Newton
Greenhorn

Joined: Nov 04, 2003
Posts: 1
Hi,
I've implemented my Data.class using a RandomAccessFile (raf) instance which I intend to share between multiple threads on the server. In order to prevent these threads from interferring with one another, as file IO is taking place, I synchronize on the raf during the statements which access it.
i.e.

As I am not caching any records in memory all of my record operations take place using the raf and all of them are synchronized. Since no two threads can operate on the same record at once (indeed no two threads can operate on the datafile at once as I synchronize on the file pointer) how can I justify the record locking mechanism provided by the lock() and unlock() methods?
Do I need to implement a more complicated scheme that allows one thread to read from a record whilst another one writes to a different record to realise the benifits of lock(), unlock()? If so then does this mean that I will have to cache the records in memory?
any advice is greatly appreciated,
Mark
Adrian Popescu
Greenhorn

Joined: Oct 08, 2003
Posts: 12
Hi Mark,
I don't think you should synchronize on raf.
Instead, try to create a lock/unlock mechanism
that will block a thread that tries to update a record
that is already locked by another thread.
By the way, what assignment do you have?
Bharat Ruparel
Ranch Hand

Joined: Jul 30, 2003
Posts: 493
Hello Mark/Adrian,
I think that Mark is on the right track but has to do additional work.
Mark, you are right that you are synchronizing on the RAF given what you are doing. You have to make sure that all your clients use the same instance of the the RAF (using static declaration or Singleton - I chose a Singleton DataSchema class which provided an instance of the RAF to the Data class). This is for physical record locking, i.e., to make sure that the file-pointer is not moved in the middle of a read/write operation.
Now you have to work on the "Logical" record locking, which you will implement in the lock, unlock, and islocked methods. Logical record locking facilitates mutual communication amongst the threads/clients which want to work on the same record. People have done it using some kind of a data structure which is made static in the Data class, others have done more elaborate work by devicing a "lock-manager". I chose to implement mine using a static HashMap (or more specifically WeakHashMap).
The important point to take away from all this is that you need:
1. Physical locking,
and 2. Logical locking
There are a number of threads that discuss this issue. I suggest you both do a search on locking and go through the threads. It is a bit time consuming, but very well worth it. You can refine your search by adding words like physical/logical etc.
Hope this helps.
Regards.
Bharat


SCJP,SCJD,SCWCD,SCBCD,SCDJWS,SCEA
Andrew Monkhouse
author and jackaroo
Marshal Commander

Joined: Mar 28, 2003
Posts: 11460
    
  94

Hi Mark,
Welcome to JavaRanch.
Bharat has already mentioned the distinction between ensuring that you have thead safe access to the physical database (to ensure you don't corrupt the physical file), and logical locking of records to ensure that only one client can book a particular client. Both are required for this assignment.
Adrian raised an interesting point (maybe - I may be misreading his post ). That is - which object do you synchronize on in order to get your thread safe access to the physical file. Synchronizing on the RAF could be fine. But you will also have synchronization elsewhere in your application to ensure that only one client can get a lock at any given time, and that synchronization is almost certainly not going to be on the RAF. That means that you will have two separate mutexs, which means that you do have to be careful about potential for deadlocks. There should be no reason for deadlock with these two particular mutexs, but you do have to think about such things, and make sure for yourself that your code is OK. Having just the one common mutex for both operations will remove that potential for deadlock, at the cost of lower performance. You might decide that this is better (especially if you are worried about that junior programmer). Personally, I don't think so - I would prefer to make sure that my code is safe with the two mutexs which logically should not interact anyway.
Regards, Andrew
[ November 05, 2003: Message edited by: Andrew Monkhouse ]

The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
Philippe Maquet
Bartender

Joined: Jun 02, 2003
Posts: 1872
Hi Mark,
I have not much to add to what Andrew, Bharat, and Adrian wrote. Just this : while you need two separate mutexs as Andrew just emphasized, one of them could support multiple concurrent reads.
AFAIK after 5 months passed on this forum, Vlad is the only guy (but me) who tried to do it. Vlad (after coding) changed his mind for simplicity (and "thanks to" Andrew ), I didn't, and I still think it's a reasonable way of synchronizing access to the RAF. After all, you shouldn't care that multiple clients read your file concurrently, right ? IMO, it's even the kind of thing you should allow. But I am quite lonely to defend that position, so don't worry about it.
Best,
Phil.
Peter Yunguang Qiu
Ranch Hand

Joined: Nov 22, 2003
Posts: 99
AFAIK after 5 months passed on this forum, Vlad is the only guy (but me) who tried to do it.

What "it" means? Does it means sychronized(raf){ } ?
Vlad (after coding) changed his mind for simplicity (and "thanks to" Andrew ), I didn't,

What did Vlad do after changed his mind? I guess he sychronized most of the methods in DataAccess class?
I didn't, and I still think it's a reasonable way of synchronizing access to the RAF. After all, you shouldn't care that multiple clients read your file concurrently, right ? IMO, it's even the kind of thing you should allow.

When you allow multiple clients read your file concurrently, don't you worry about file-pointer moved in the middle of a read operation?
If RAf is synchronized, is it possible to allow more than one clients to read concurrently?
Or when you read, you don't synchronizing RAF? only synchronizing RAF when you write?


Peter
Peter Yunguang Qiu
Ranch Hand

Joined: Nov 22, 2003
Posts: 99
You have to make sure that all your clients use the same instance of the the RAF (using static declaration or Singleton - I chose a Singleton DataSchema class which provided an instance of the RAF to the Data class).

Assume a class has three methods and three instance variables, if I make all three methods and all three instance variables static, is this class equivalent to a singleton?
Bharat Ruparel
Ranch Hand

Joined: Jul 30, 2003
Posts: 493
Hello Peter,
Good question. I am going to simplify it further:
A class that has only one static variable - Is this an instance variable? Not really, since it is to be shared by all the instances of this class and is at the class level. That is, no matter how many instances you create of this class, you can access this variable from anywhere any point (provided that you have the right visibility), and any instance can change the value for this variable. Further, the changed value is available to all other instances. Therefore, a static variable is a shared resource (or state) amongst all instances of the same class.
What is a Singleton? A singleton pattern is typically used to control the "number" of instances that can be created for a class. Frequently, the number of instances is limited to one. Another term that you hear on this forum for a controlled number of instances is a "multiton" implying that more than one number of instances are being created by still in a controlled manner. The Singleton instance is instantiated by another object or objects. In the example here, the Data class Objects are instantiating only one instance of "DataSchema" and sharing it amongst themselves, but the DataSchema class still is a valid, free-standing, legitimate class that encapsulates a certain amount of functionality.
Compare this to the "lockedRecords" WeakHashMap static variable in the Data class. Granted that WeakHashMap is a free-standing, legitimate, generic class of the new JDK Collections framework that encapsulates a certain amount of functionality. Within the context of our SCJD assignment, more specifically, within the instances of the Data class, it simpler and more natural to use it as a inner and shared resources that doesn't have much meaning outside the context of the Data class.
Therefore, a better object-oriented design trade-off is to make the lockedRecords instance a static or class level object and keep the DataSchema class a Singleton. As soon as you start to do "more" things with the lockedRecords instance variable which are centered around its functionality, you are really talking about a "LockManager" class which without a doubt, will make use of some data-structure similar to the WeakHashMap. Now, you may want to use this "LockManager" class as a Singleton within the Data class instances.
So what am I driving at? There are no cut and dry answers to your question. Both static variables and Singleton design patterns address similar issues. The choice of one over the other depends on the context of the problem being solved. A static variable can later be evolved to a full-blown "Singleton" class based on your needs. My inner guiding principle is to keep the things simple as much as I can so that anybody can understand it (including myself).
Years ago, when I was experimenting with object-oriented design and programming, and more specifically, late-binding. I reduced a 30,000 lines of dBase III program written by me to under 3000 lines of Clipper code and actually added quite a bit more functionality. I was so proud of it that I wrote three papers which were published in the leading industry journals. A year later, the users came to me for inevitable "maintenance." Imagine my shock, when it took me close to a week just to get started since I couldn't undertand my own code and design because of many levels of indirection that I had created in my academic persuit of indirection/polymorphism/data-driven programming or whatever you may want to call it.
Now I design things so that I can understand it later and hopefully, some poor soul charged with maintaining my code has a fighting chance to understand it. If you keep that in mind, you will begin to make decisions when to use a static and when to use a Singleton. Be aware that today's static can evolve to a Singleton tomorrow.
Hope I haven't cofused you any more. Actually, Max's book does a good job of showing you "simple" design decisions without being academic. If I were you, I will buy it and go through it many times until some of the "simple" design philosophy begins to rub-off.
Best Regards.
Bharat
[ January 11, 2004: Message edited by: Bharat Ruparel ]
[ January 11, 2004: Message edited by: Bharat Ruparel ]
Jason Mowat
Ranch Hand

Joined: Aug 17, 2003
Posts: 79
Greets,
I have seen the synchronization debate going on in a few threads in this forum. FWIW, I have posted a solution at this location outlining a ReadWriteLock strategy for addressing the whole synchronization issues with the file.
Hope this helps!
Cheers,
Jason
Philippe Maquet
Bartender

Joined: Jun 02, 2003
Posts: 1872
Hi Peter,
What "it" means? Does it means sychronized(raf){ } ?

Allowing concurrent reads / exclusive writes. To achieve that, you need to write a special class (I call mine MultiReadSingleWriteSynchronizer) that you then use instead of built-in synchronization.
Now it looks like Jason has a similar approach.
What did Vlad do after changed his mind? I guess he sychronized most of the methods in DataAccess class?

Simple synchronization (exclusive reads and writes).
When you allow multiple clients read your file concurrently, don't you worry about file-pointer moved in the middle of a read operation?
If RAf is synchronized, is it possible to allow more than one clients to read concurrently?
Or when you read, you don't synchronizing RAF? only synchronizing RAF when you write?

It really depends on your design. As RandomAccessFile is not thread-safe, you cannot allow multiple clients using the same RAF instance concurrently. BUT, you can :
  • use temporary connections to your file, through local RAF instances;
  • or better, use a pool of RAF instances;
  • or even better (and much simpler), use a FileChannel got from your RAF : FileChannel is thread-safe and allows concurrent access through the methods which take an explicit position.


  • Regards,
    Phil.
    Peter Yunguang Qiu
    Ranch Hand

    Joined: Nov 22, 2003
    Posts: 99
    Thanks Bharat and phil
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: NX: RandomAccessFile synchronization and record locking