Win a copy of Building Blockchain Apps this week in the Cloud/Virtualization forum!

Rod Sinclair

Greenhorn
+ Follow
since May 11, 2010
Cows and Likes
Cows
Total received
0
In last 30 days
0
Total given
0
Likes
Total received
0
Received in last 30 days
0
Total given
0
Given in last 30 days
0
Forums and Threads
Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by Rod Sinclair

Hi

Looking for a Java contract in the UK. Please contact for further details.

Regards

Rod
9 years ago
First of all thank you to the people who post on this board and help out with this certification.

Got my pass mark today from Oracle.

I used serveral books on Swing, Multithreading and Sockets but the most useful is Monkhouse et al.

Sockets were used for performance reasons and it turned out to be relatively few lines of code. I did not make the Data class a singleton, each thread has its own instance of Data and its own file handle to the raf. This means that I did not have to synchronize the delete and update methods. Different records can be locked and updated or deleted simultaneously which improves performance.

After submission I did find one potential issue with the double checked locking that I had used in the SavedProperties class in that I did not make the instance volatile. This can result in out-of-order writes because of the Java memory model.

Rod
9 years ago
Roel - here is the secret. I call lock and unlock inside the read method to lock the record, just around the critical section of code. You can use my read code without first locking and then unlocking. It is thread safe.

I use a static lock object (java.util.concurrent.locks.Lock) that is shared amongst all instances of the Data class. In my lock method I first have to get a lock on the static lock object. I then check a static HashMap to see if the record is locked. If it is I wait if not I continue, enter the recNo in the HashMap locking the record. I then unlock the static lock object so another thread can get in.

The create method is threadsafe because to execute create you first have to get a lock on the static lock object. Once this is achieved all other threads must wait. The create method is the only method that needs to be locked for the duration of execution.

As I said previously delete and update can be executed in a threadsafe manner without synchronizing these methods. The record has already been locked in the lock method. As I said before the secret to maximum concurrency is not to make Data a Singleton. Then each instance of Data has its own handle to the raf which means that different records in the database can be read, updated and deleted concurrently. Each thread has its own pointer to the raf. Remember, local variables are threadsafe. Static variables are used to coordinate the locking.
Roel - It sounds from your response that you do synchronize read. It would not work otherwise. I use the record locking mechanism provided by lock and unlock to achieve the same thing in read i.e. making critical sections of code threadsafe. My system is designed so that multiple threads can update and read different records at the same time because my synchronization is fine grained. Using synchronize locks the entire database.
Roel - are you sure that reading without any synchronization is thread-safe? There is a critical section of code in read.
Roel - I lock a record in the read method before the calls to seek and readFully. This is because another thread could be updating the same record at the same time the read is taking place in which case read would return a corrupted record. I assume that you synchronize the entire read method to prevent this happening.

An optimistic locking mechanism sounds complicated. It is simpler to not reuse record numbers and Oracle say keep it simple.
Roel - we will have to agree to disagree on what is meant by designing for future functionality enhancements. In my design because I have not reused record numbers create and delete can be added without altering the way I deal with record numbers.

Roberto - there is a difference between reusing the disk space occupied by a deleted entry and reusing the record number. Oracle suggest reusing the disk space but that does not mean that you can reuse the record number. In my design the create method over writes a deleted entry and the new record is assigned a new record number.

In the example I gave earlier you spotted the mistake where I said I delete record 2 and then lock record 2 on create. Obviously I don't do this. I have given the example again, this time correct.

Client B locks record 2.
Client B reads record 2.
Client B unlocks record 2.

Client A locks record 2.
Client A deletes record 2.
Client A unlocks record 2.

Client A creates new record recNo 2 reused.

Client B now has stale data for record 2. A new record has been created in the database and assigned recNo 2.

Client B locks record 2.
Client B books record 2, wrong hotel.
Client B unlocks record 2.

If you reuse record numbers I cannot see how the above scenario can be avoided.
Norbert -

You must implement all methods in the interface. You quote from the specification "Your data access class must be called "Data.java", must be in a package called "suncertify.db", and must implement the following interface:".

Roel - just because create/delete are not referenced in the project does not mean that you can reuse record numbers, plan for future functionality. You are not displaying impeccable logic.
I'm not sure but I think that Oracle/Sun are expecting us to code for create and delete in which case you cannot reuse record numbers. I could be wrong on this though.
If you reuse record numbers do you maintain a HashMap of record numbers and mark the ones that are deleted?
Consider this:

Client B locks record 2.
Client B reads record 2.
Client B unlocks record 2.

Client A locks record 2.
Client A deletes record 2.
Client A unlocks record 2.

Client A locks record 2.
Client A creates new record recNo 2 reused.
Client A unlocks record 2.

Client B now has stale data for record 2.

Client B locks record 2.
Client B books record 2, wrong hotel.
Client B unlocks record 2.

Rod
Hi,

If you reuse record numbers there is always this possibility.

Client B reads record 2.
Client A deletes and updates record 2.
Client B books record 2.

Client B will book the wrong room in the wrong hotel because the record number is stored on the client.

Oracle's specification states that "Your user interface should be designed with the expectation of future functionality enhancements...". These enhancements would obviously include delete and create. So you should not reuse record numbers.

Rod

Hi

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.

Regards

Rod
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.
Hi,

Thanks for the responses.

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.

Regards

Rod