I have the BandS project. In order to get to my data class you must call methods from my Adapter class which then calls the Data class. In my adapter class any method that changes data must follow the standard contract (in this example I use book): lock dosomething unlock
I have one instance of Data for all clients and I lock on the record number of the contract. Is it redundant to have the book method synchronized (or any of the methods for that matter). I have become confused on this from reading to many posts. I would think not becuase the methods manipulates the file handle so I can't just be concerned with the contractor/record. At the moment I have the entire method synchronized, would it be better to just sychronize on the file handle? Thanks a ton, bill
I'm doing the URLyBird one, but here's how I went around it. I didn't synchronize any methods. It could create a bottleneck, since only one thread could call your method at one time, even if they all lock, book, unlock separate records. That's about as far as I can help you, without knowing more about how you're doing things. I did a 3-tier approach, so my booking method did the locking and unlocking itself. Therefore, the locking would block when necessary taking care of any synchronization issues by itself. My business methods are oblivious to the fact that there are synchronization issues at hand (other than the necessity to lock a record before booking, obviously).
Is it redundant to [synchronize methods]. I would think not becuase the methods manipulates the file handle so I can't just be concerned with the contractor/record.
The logical locks granted by the lock() and unlock() methods do not save you from needing synchronization around your file access - you still need synchronization at some point (whether it is at the level of the methods in your Data class, or somewhere else depends on your design). Typically when you work with the database file, you are going to do two distinct file operations: a seek() to the record you want to work with, followed by a read() or a write(). If you do not have synchronization, two threads could try and do file operations at the same time. Consider what happens then:
thread A seeks to record 5
thread B seeks to record 12
thread A reads record 12
thread B reads record 13
As you can see - without any synchronization, the wrong records were accessed, and if there had been any updates, your database may no longer be valid.
At the moment I have the entire method synchronized, would it be better to just sychronize on the file handle?
Synchronizing a method might be easier for a junior programmer to understand. But as Nathaniel says, doing so blocks access to the entire method. Do you do other work in the method which can be done outside the synchronized block? For example, if you do your conversion from US-ASCII to bytes, and build one long byte outside the synchronized block, then your system would be a tiny bit more performant than a system that does that work inside a synchronized block. As always, it is a design decision. And having made that decision you need to document it.
Is it redundant to have the book method synchronized (or any of the methods for that matter).
I would not synchronize the high level book() or find() methods. Each of your higher level methods calls multiple lower level methods (such as lock(), read(), update()) and does some processing, which means you would be blocking other clients from calling the higher level methods. I would recomend you keep the synchronization at lower levels. Regards, Andrew
Greets, One design decision I made was to not synchronize my file access methods in my concrete data class, but to rely on a seperate thread locking manager class. This follows Grand's ReadWriteLock pattern, and it works fabulously with a small amount of code. In essence, your database concrete class would have a ReadWriteLock class. Before you call any method that performs a read operation (like read(int)), you first call the lock manager's readLock method. When you have completed the read operation, you call the lock manager's done method. Furthermore, when you perform a write operation (like create(String), delete(int), etc...), call the lock manager's writeLock method before the operation, and call the done operation when you are done writing. The lock manager will manage your threads so that they enter wait states while a thread performs a write operation. One the write operation of one thread is completed, the class checks to see if there are any other write requests pending. If there isn't, it processes ALL of the read operations. The benefit is that you don't have to lock the entire class by marking key methods synchronized. You also get a side benefit of your read operations always getting the most up-to-date information, especially if there are a lot of simultaneous writes going on. The code that I used is as follows:
Hope that helps! Cheers, Jason [ February 21, 2004: Message edited by: Jason Mowat ]