I have noticed that some people synchronize all methods in the data class. In that case why do you need to lock a record prior to update or delete. If the method is synchronized only one thread can access it at a time. The problem with this is that you lose concurrency, only one thread can update or delete a record at a time. Two threads wanting to update or delete different records will not be able to do so at the same time.
With my approach there is no locking in the update and delete methods. My Data.lock function locks a record so that only one thread can update or delete a given record at a time. However, multiple threads can update or delete different records at the same time, due to the fact that they lock different records, without corrupting the database which means that the system is concurrent.
Just wondering though is there any solution to avoid synchronizing the update and delete method so that multiple threads can write to different records at the same time by just using the lock and unlock methods? I do realise that you cannot update and delete the same record simultaneously but this is handled by the lock method locking the record before update or delete.
That's the whole purpose of the Data class: different records being updated/deleted simultaneously (concurrently). And the performance depends on how "big" the synchronized blocks you use to make your Data class thread-safe.
Joined: May 11, 2010
If you synchronize the update and delete method at all they are not concurrent, only one thread can be executing the synchronized code at a time.
My understanding is that the lock method takes care of preventing threads updating the same record at the same time (which would cause corruption) but different threads should be able to update different records at the same time. If you synchronize update and delete you cannot have two different threads updating the database at the same time because synchronized code can only be entered by one thread at a time.
Rod Sinclair wrote:synchronized code can only be entered by one thread at a time.
That's also true for the CPU: can only be entered by one thread at a time. So different threads updating different records at the same time is not possible, because only 1 thread will have CPU time at any given time (maybe it would be possible when you have multiple CPUs, but I don't have an idea how the JVM scheduler does his work when having multiple CPUs).
But if you want a more performant solution, you can always use synchronized blocks instead of synchronized methods. But you will always have a synchronized block, because you don't want your database file to be corrupted.
If you don't synchronize these 2 statements and make it an atomic operation, you risk a thread being kicked from CPU after moving the file pointer to the desired location, and another thread moves the file pointer to another location (and reads a record), and this thread writes to a wrong location (updating a completely wrong record)
Joined: May 11, 2010
I take your point regarding only one thread entering the CPU at a time, however there is still a performance penalty with using synchronized code.
In my solution the Data class is not a singleton. Each thread has its own instance of Data. In the constructor a file handle is opened to the raf so each thread has its own handle to the database. This means that different threads can call seek without affecting another threads file pointer because local variables are thread safe. I can therefore update and delete different records without any synchronized code in update and delete (improves performance) because each thread is writing to different parts of the database and has its own file pointer on the call stack.
The lock method locks a record preventing two threads from updating or deleting the same record at the same time which would cause corruption.
Rod Sinclair wrote:there is still a performance penalty with using synchronized code
If you have read your instructions carefully you know that a simple less performant approach is preferred above a more complex, more performant one. The approach with synchronizing complete methods is as simple as possible.
If each thread has its own Data instance you need to use static members to share information between these instances. Otherwise I don't see howh a thread could give up CPU if it tries to lock a record that's already locked. So you won't be able to reuse your Data class for handling a customer database file.
This is just a choice I/you made, just like any other (design) choice you make and every choice has its pros and cons. As long as you don't violate any "must" requirement, any approach is valid and will make you pass this certification.