jQuery in Action, 2nd edition*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes My locking approach Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of JavaScript Promises Essentials this week in the JavaScript forum!
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "My locking approach" Watch "My locking approach" New topic
Author

My locking approach

Ryan Tang
Greenhorn

Joined: Aug 20, 2003
Posts: 18
Hi,

Recently I passed the exam, and got 80/80 for the locking part. I would like to share what I have done which may be helpful for you to determine what Sun expects us to write.

If my post violates the rule, I am willing to apologize and please kill this post.

I use the simplest approach, static HashMap(not a weak one) storing the locked records and cookies, and it is synchronized whenever it is being accessed.

For update, first I check if the record is being locked by the specified cookie within the HashMap sync block. Then I perform the actual I/O update out of the sync block.

For delete, I do similarly as update, but include another HashMap sync block after delete to remove the locked record.

For lock, I perform the checking "is record already locked" and "does record exist" in the HashMap sync block, and wait if the record is already locked. Cookie is returned if lock is placed. It is the simpliest design.

For unlock, I perform record existence checking out of the HashMap sync block. I check if record is locked by the specified cookie and remove the locked record entry in the sync block.

I cache the database file using an ArrayList. For update and create operations, both the cache and database file are updated together. This caching logic is implemented in another class, CacheManager. It has methods like read, update and create to be used by the data access class. All these methods synchronize on the private ArrayList instance.

Last advice, KEEP THINGS SIMPLE!

Hope it helps.

Best wishes,
Ryan
Paul Bourdeaux
Ranch Hand

Joined: May 24, 2004
Posts: 783
Thanks Ryan. Your score is good news to me, as I implemented my locking in almost the exact same way (except I chose not to use a cache). Hopefully I will score as well!

I would be very interested to hear from some of the JavaRanch members who received the infamous 44/80 on their locking. How does it compare to Ryan's code?


“Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning.” - Rich Cook
Frank Verbruggen
Ranch Hand

Joined: Feb 01, 2005
Posts: 37
I'm wondering, what did u do to avoid that a record be locked forever when it is locked by a process and then that process dies.
It can never release its lock then ?
Regards


----------------<br />SCJP (98%)<br />SCJD (81%)<br />SCEA (near future)
Ryan Tang
Greenhorn

Joined: Aug 20, 2003
Posts: 18

I'm wondering, what did u do to avoid that a record be locked forever when it is locked by a process and then that process dies.


Nothing.

It can never release its lock then ?


Yes.
Frank Verbruggen
Ranch Hand

Joined: Feb 01, 2005
Posts: 37
Weird
I was lead to believe that that made a whole lot of difference.
a bunch of books and some people keep on warning about processes locking records and never releasing them.
See for instance the 44/80 locking topic somewhere in this forum.
At least that helps me out a lot.
Yet another question.
I am making quite an elegant design caching, and reading my records with a nice approach involving a ColumnHeader class, a ColumnHeaders class, a Record class and a Records class. All of these contribute to reusable code.
What I'm wondering, did u also use a lot of objects,
or did u prefer a fast primitive typed solution ?
Cause, I'm starting to think that all of this could be a bit overwhelming for a junior programmer, and the assignment clearly stated that it should be written in such a way as is readily understood by a junior programmer.
Some tips maybe ???

Thanx in advance

(O and BTW congrats on ur great score for locking and passing the SCJD ! )
Ryan Tang
Greenhorn

Joined: Aug 20, 2003
Posts: 18

I was lead to believe that that made a whole lot of difference.
a bunch of books and some people keep on warning about processes locking records and never releasing them.

May be I was punished for not implementing that in "General Consideration", if you see my score in the certification result forum.

What I'm wondering, did u also use a lot of objects,
or did u prefer a fast primitive typed solution ?

Just String[].

I did create something like a "Column" class, but it is used for returning the column name to the client for constructing the JTable.
Frank Verbruggen
Ranch Hand

Joined: Feb 01, 2005
Posts: 37
Well, maybe I can post u some code over mail.
I would like to hear your advice on my LockManager class,
and the structure I use for reading the database.
Is that OK to exchange email adresses for this purpose ???
If not Im very sorry ....
Greetz
Paul Bourdeaux
Ranch Hand

Joined: May 24, 2004
Posts: 783
I was lead to believe that that made a whole lot of difference.
a bunch of books and some people keep on warning about processes locking records and never releasing them.
This is mostly speculation about what can cause the mysterious 44/80 score - nobody knows for sure yet. I, like some others on this site, believe that managing for orphaned locks is outside the scope of this project. Ryan's score seems to support this theory. Again, I hope some of the people who have scored 44/80 will give us a detailed explanation of their locking solution so we can compare it to Ryan's.
Vincent Hernandez
Ranch Hand

Joined: Oct 17, 2004
Posts: 43
Hi Ryan. Thanks for posting some insight into your locking strategy.

I'm a bit confused on a couple points you make within. Perhaps it was your wording, but I want to see if you can clarify.

From what I can gather I can assume a couple things, which sounds fine:
1) You lock a record before calling an update or delete operation.
2) You unlock a record after calling an update or delete operation.

For update, first I check if the record is being locked by the specified cookie within the HashMap sync block. Then I perform the actual I/O update out of the sync block.


Are you synchronizing on your HashMap within your update method? If so, why? It makes no sense to me to do such if all you are doing is a lookup. My understanding is that you should only synchronize the HashMap (or whatever locking structure you may have) during times you plan to delete (during unlock) or add (during lock) operations.

For delete, I do similarly as update, but include another HashMap sync block after delete to remove the locked record.


Again, I'm not sure what you mean by this. Are you talking about your unlock record operation? Also, shouldn't unlockRecord handle the deletion of the locked record number?
Ryan Tang
Greenhorn

Joined: Aug 20, 2003
Posts: 18

Are you synchronizing on your HashMap within your update method? If so, why? It makes no sense to me to do such if all you are doing is a lookup. My understanding is that you should only synchronize the HashMap (or whatever locking structure you may have) during times you plan to delete (during unlock) or add (during lock) operations.

Quoting from the JavaDoc of HashMap:

If multiple threads access this map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally.

My interpretation on this is that I need to synchronize the HashMap EVERY time when it is being accessed, as there are some threads that "structurally" modify the thread.

Again, I'm not sure what you mean by this. Are you talking about your unlock record operation? Also, shouldn't unlockRecord handle the deletion of the locked record number?

My data access interface requires throwing RecordNotFoundException when unlock is called.
Thus my client does not(and actually is not allowed to)call unlock after delete. It is the delete method responsibility to clean up the locked record entry in the HashMap.
Vincent Hernandez
Ranch Hand

Joined: Oct 17, 2004
Posts: 43
Aha! Ok that makes sense to me now. Thanks Ryan.

As for the second reply you make, my interface is different than yours, and unlock does not throw RecordNotFoundException, only SecurityException. This makes much more sense.

Just out of curiousity, why did you chooese HashMap over Hashtable?
Ryan Tang
Greenhorn

Joined: Aug 20, 2003
Posts: 18

Just out of curiousity, why did you chooese HashMap over Hashtable?

Hashtable is somehow a "legacy" data structure in Java. HashMap is newly introduced in Java Collection Framework with Java 1.2.
You can have a look on this for more details.
peter wooster
Ranch Hand

Joined: Jun 13, 2004
Posts: 1033
Originally posted by Ryan Tang:

Hashtable is somehow a "legacy" data structure in Java. HashMap is newly introduced in Java Collection Framework with Java 1.2.
You can have a look on this for more details.


More than that, for this use there is a real reason not to use a synchronized collection. You need to have you own synchronized methods or blocks so that you can use wait and notifyAll. These blocks will access the collection. If the collection is also synchronized, you will have nested synch blocks, which are a bad idea since they encourage deadlocks and they interfere with performance.
Frank Verbruggen
Ranch Hand

Joined: Feb 01, 2005
Posts: 37
I have had the following idea:

I use a ClientDataAccess class that hides the lock and unlock methods from the client.
This class implements all methods for using records,
and delegates them to the Data class whoch implements DBAccess, the data access interface.

To keep records from ever holding a lock this class manages the locking and unlocking strategies. Thus, when a client dies, the lock on a record is automatically released, because the method will finish executing on the server, and release the lock.

Furthermore, I dont use record based locking, but instead I lock the entire table by making all methods synchronized.
This is called table based locking, and is also used in MySQL.
Because the table ALWAYS needs to be locked before a record can be "locked"
there can NEVER EVER be any inconsistencies in the database.
Furthermore, since clients have no clue that a Data class exists, no client shall ever know of a long representing a records lock, thus preventing weird problems.

This code is quite simple, and very object oriented, and requires about 50 lines of code.

I can't think of anything better.
But I would like to hear some response from u readers out there!
Is there a flaw in my design ???
I cant seem to think of one.

Note, table based locking is NOT slower than record based locking......
So PLEASE dont come with comments about that.

Greetz
peter wooster
Ranch Hand

Joined: Jun 13, 2004
Posts: 1033
Table based locking is probably faster than record based locking, in terms of CPU consumed. It does allow a single user to interlock a much larger portion of a system before going for lunch. This isn't a problem if its strictly on the server, but is an issue if you expose it to clients.

I'm not certain that you would get full marks for that approach since the spec is for record based locking. Has anyone who's passed used this approach?
Frans Janssen
Ranch Hand

Joined: Dec 29, 2004
Posts: 357
Frank,

If I understand your design correctly, your building a so-called thin client, where the business logic is all implemented server side, e.g. a book method.

This defies the need for a lock() method in the interface, as your description confirms. For this reason a lot of people, including myself, assume that this design is not what Sun describes as "a traditional client-server system". There are numerous threads on this issue on this forum.

On the other hand, people have passed using similar designs, so second-guessing Sun's deeper motives is maybe taking the assignment to seriously

Although I feel that your design deviates from the direction that your instructions point us, I see no flaws design-wise.

Frans.


SCJP 1.4, SCJD
Vincent Hernandez
Ranch Hand

Joined: Oct 17, 2004
Posts: 43

More than that, for this use there is a real reason not to use a synchronized collection. You need to have you own synchronized methods or blocks so that you can use wait and notifyAll. These blocks will access the collection. If the collection is also synchronized, you will have nested synch blocks, which are a bad idea since they encourage deadlocks and they interfere with performance.


I have to disagree with this. As the Habibi book explicitly points out, all a synchronized class guarantees is that it's actions are atomic. If one thread calls for an add operation to a sychronized structure and another calls for a read, one operation will be done before the other. However, because it's a question of which occurs first, there needs to be synchronization in order to manage the structure in multi-threaded situations.

As for encouraging deadlocks, calling a sychronized method such as Vector's add inside a sycrhonized block on the vector object will not cause deadlock. once the IP hits the sychronized block line, the thread that exectued it owns a lock on the object. When the add is called, the same thread still owns the object.

Hashtable is somehow a "legacy" data structure in Java.

I do not see any label to Hashtable indicating it is depricated. However, seeing how you used your HashMap, you took all the proper precautions that were necessary.
Frank Verbruggen
Ranch Hand

Joined: Feb 01, 2005
Posts: 37
Originally posted by Frans Janssen:
Frank,

If I understand your design correctly, your building a so-called thin client, where the business logic is all implemented server side, e.g. a book method.

This defies the need for a lock() method in the interface, as your description confirms. For this reason a lot of people, including myself, assume that this design is not what Sun describes as "a traditional client-server system". There are numerous threads on this issue on this forum.

On the other hand, people have passed using similar designs, so second-guessing Sun's deeper motives is maybe taking the assignment to seriously

Although I feel that your design deviates from the direction that your instructions point us, I see no flaws design-wise.

Frans.


You raise an interesting point, but after having read the description provided in the assignment fully, I figured out that it clearly states the following:

SERVER
Required Interface

Your data access class must be called "Data.java", must be in a package called "suncertify.db", and must implement the following interface:


This means that for accessing my data, server-side ! I must have a clasds called "Data.java" in package "suncertify.db", NOTHING is mentioned about having to expose this interface to the clients !!!

So I plan not to.

Comments ??
Frans Janssen
Ranch Hand

Joined: Dec 29, 2004
Posts: 357
Originally posted by Frank Verbruggen:


This means that for accessing my data, server-side ! I must have a clasds called "Data.java" in package "suncertify.db", NOTHING is mentioned about having to expose this interface to the clients !!!

So I plan not to.

Comments ??


Hi Frank,

I do agree that your approach (or the thin client approach in general) does not violate any of the musts in the assignment. And that is why people pass using such an approach, so you'll probably be safe with your design.

However, I still feel that because the interface declares a lock method, that should be taken as a hint that this method should be exposed over the network. Otherwise you could implement it as an empty method and that is probably not how the person that defined the interface meant it to be.

When I started the assignment, my first hunch too was to make a thin client, but I changed my mind when I realized that I then would have no purpose for the lock method.

Frans.
Frank Verbruggen
Ranch Hand

Joined: Feb 01, 2005
Posts: 37
Originally posted by Frans Janssen:


Hi Frank,

I do agree that your approach (or the thin client approach in general) does not violate any of the musts in the assignment. And that is why people pass using such an approach, so you'll probably be safe with your design.

However, I still feel that because the interface declares a lock method, that should be taken as a hint that this method should be exposed over the network. Otherwise you could implement it as an empty method and that is probably not how the person that defined the interface meant it to be.

When I started the assignment, my first hunch too was to make a thin client, but I changed my mind when I realized that I then would have no purpose for the lock method.

Frans.


On the other hand, making this the approach extremely simplifies the locking mechanism, thus allowing me to know for sure this will work.
Also using this design improves code clarity.
Since the assignment DOES state:
Use of functionality provided by the core Java classes will be prefereed to your own implementation of that functionality

and ALSO:
A clear design, such as will be readily understood by junior programmers, will be preferred to a complex one

I think they want u to make the desicion that the lock and unlock should be implemented using smart synchronization, whihch is something my approach readily takes care of.

What do u think
Evans Tapia
Greenhorn

Joined: Jan 21, 2005
Posts: 5
Originally posted by Ryan Tang:

For update, first I check if the record is being locked by the specified cookie within the HashMap sync block. Then I perform the actual I/O update out of the sync block.

For delete, I do similarly as update, but include another HashMap sync block after delete to remove the locked record.

For lock, I perform the checking "is record already locked" and "does record exist" in the HashMap sync block, and wait if the record is already locked. Cookie is returned if lock is placed. It is the simpliest design.

For unlock, I perform record existence checking out of the HashMap sync block. I check if record is locked by the specified cookie and remove the locked record entry in the sync block.



Hi Everyone,

I'm a little confused, do you verify the locking of records from the update, delete, ... methods in your Data class? or in another adapter class?

Because, I was planning to implement the Adapter pattern, in this way I implement the update, delete, etc methods in the Data class without worrying about calling lock and unlock from there.

Then build a DataAdapter class which will call the update, delete, ... methods from data calling lock and unlock, something like...

class DataAdapter{
...
update(...){
data.lock(...);
data.update(...);
data.unlock(...);
}
}

If the people who is going to test my Data class is going to test dalete and update without calling explicitely lock and unlock before and after, obviously the Data implementation is not going to pass the locking requirements.

Do you have an adapter class that hides lock and unlock from the client?

If you are checking if a record is locked (for the update, delete,... methods) using the sync block and not lock and unlock, then why do we need the lock and unlock methods for?

Thanks,
Evans
Vincent Hernandez
Ranch Hand

Joined: Oct 17, 2004
Posts: 43
Evans,

At least in my case, the answer is no. I looked at the adaptor pattern and saw how it was utilized within the Habibi book, but looking ahead I saw I would have many complications with my business logic layer.

For instance there's a situation in my business code where I need to do the following:

1. lock the record to be updated.
2. read the record.
3. verify the record has not been updated in a particular field.
4. update the record.
5. lock the record.

Now, let's say I wanted to use an adaptor class. Ideally, this is what I'd want to see in a complimentary business method:

1. read a record (assume it's a safe, clean read which is done in the code).

After 1 is done, your record is unlocked...
<<someone in another thread updates before 2 can be run!>>

2. update a record (lock and unlock done in data adaptor).

Now, I thought about creating a data adaptor class, but then I started to see that there were special rules involved with that, like the check to see if the owner id was filled, etc. That sounded to me more like a business rule, so I decided to put my business logic layer on top of the data access layer.

I'd like to hear how others handled this part.
Frank Verbruggen
Ranch Hand

Joined: Feb 01, 2005
Posts: 37
I also decided to use the adapter pattern,
I made my adapter implement these business rules.
The way to enforce that the methods dont interfere is to synchronize.
Then implementing business logic is easy.
Frans Janssen
Ranch Hand

Joined: Dec 29, 2004
Posts: 357
Originally posted by Frank Verbruggen:

I think they want u to make the desicion that the lock and unlock should be implemented using smart synchronization, whihch is something my approach readily takes care of.

What do u think


Hi Frank,

It's funny you always end with this question, even though we clearly seem to disagree on the subject

But to repeat the obvious: I do not think that Sun wants you to use smart synchronization; I think the mere presence of the lock method suggests you should implement a fat client.

HOWEVER, I do believe that making a thin client using server-side ("smart") synchronization with dummy lock and unlock methods* will make you pass the exam. If you believe that this is the better solution, explain it in your choices.txt and you will be fine.

What do you think?

Frans.

* I am curious how you will implement the lock and unlock methods, because your solution will not need them, but your interface requires you implement them according to the specification. Can you tell me what your lock method will do?
 
Consider Paul's rocket mass heater.
 
subject: My locking approach