I have been working on the B&S assignment for about a month now and my work is getting along fine (for which I am everyone on this forum very greatful since the discussions here have been of invaluable help to me). But I am stuck with kind of a moral dilemma concerning my locking. So far I have worked out 2 solutions to locking and both are working fine. 1) Put the locked records in a Map, wait on the Map and call notifyAll whenever a lock is released 2) Use a map with 'RecordLocker' objects (consists of a recordNo and a locked/not locked status) and then wait on those objects and call notifyAll on the RecordLocker objects when a lock is released.
Personally I prefer solution 2 since it seems to better fullfill the following requirement, because notifyAll in solution 1 might wake up threads that are not waiting for the record that was unlocked, which is not the case with solution 2.
Any attempt to lock a resource that is already locked should cause the current thread to give up the CPU, consuming no CPU cycles until the desired resource becomes available.
But on the other hand, if I use solution 2 I do have a problem related to releasing the RecordLocker objects of unlocked records. Here is the pseudocode for my lock and unlock:
The problem is in the line marked with (*). If I don't try to remove the RecordLocker from the 'lockers' Map everything works fine. But if I do, I should only remove it from the Map if I am sure no other threads are waiting for the RecordLocker or even worse have a reference to the RecordLocker object but have not yet tried to lock it (and thus are not yet waiting on the RecordLocker but will be in some very near future).
This pretty long story brings me to my actual question. I guess I could find a solution to solve this problem, but that would add more complexity to locking solution 2, which is already more complex than solution 1.
So I was hoping someone could help me choose the least of two evils a) Should I keep it simple, follow solution 1 and live with the minor CPU penalty that comes with waking up threads unnecessarily? b) Should I go with solution 2 without deleting the RecordLocker objects and live with a scalability problem (if the database becomes huge, the Map becomes huge)? c) Should I go with solution 2 and make it perfect but more complex?
Personally I would go for b) because it is my preferred locking solution and the whole system is not scalable anyway so why bother with the size of the 'lockers' Map.
Actually, if look back at this mail, it astonishes me how far the guys from Sun have been able to drive me. In a real work situation I would just pick the best solution based on the application specs. But now I am totally paranoid in finding the best solution only to get a good score on this assignment. Call me a freak.
A possible alternative to your solutions we be to use "hand-over-hand" locking using JDK 5 reentrant locks. This is described clearly in Andrews book in the section on "Multiple Notification Objects" p. 157. To quote the book:
Under JDK 5 you can have all your threads obtain a lock on the same object but use different Conditions upon which they should be notified.
Hope this helps
Sun Certified Developer for the Java 2 Platform
Sun Certified Enterprise Architect for the Java Platform, Enterprise Edition 5
posted 14 years ago
thank you for the tip. I just ordered Andrew's book, so I'll get back to my locking when it arrives. Still plenty of other stuff to do.
posted 14 years ago
Just in case someone might be struggling with the same questions I had, I thought It might be interesting to post my final decision on this matter.
After reading Andrew's book, I finally decided to go for solution b), since the footprint of keeping all locks in memory should be small enough compared to the possible advantage of lower CPU charge.
Even using the hand-over-hand locking possibilities of J2SE5 I couldn't find an easy implementation for solution c). So this decision is partly based on a choice for simplicity.