|
![]() |
SCJP 1.4<br />SCWCD 1.3<br />SCJD<br />SCBCD<br />IBM Xml Cert in progress
The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
SCJP 1.4<br />SCWCD 1.3<br />SCJD<br />SCBCD<br />IBM Xml Cert in progress
SCJP 1.4<br />SCWCD 1.3<br />SCJD<br />SCBCD<br />IBM Xml Cert in progress
SCJP 1.4<br />SCWCD 1.3<br />SCJD<br />SCBCD<br />IBM Xml Cert in progress
SCJP 1.4<br />SCWCD 1.3<br />SCJD<br />SCBCD<br />IBM Xml Cert in progress
// If the specified record is already locked, the current thread gives up
// the CPU and consumes no CPU cycles until the record is unlocked
Originally posted by Lara McCarver:
I have created a Vector of RecordLock, with one RecordLock per database record. Each record lock keeps track of whether it is locked and if so, which object locked it.
I initially had a notifyAll() at the end of my lock() method, just before I exited, just like you. However, I eventually realized that locking a record did not make another waiting record eligible to use it, and in addition, the requirement
does explicitly say to only use the CPU when the record is unlocked. so I changed to only do a notifyAll() on the unlock() method.
[ June 20, 2005: Message edited by: Lara McCarver ]
Originally posted by Alan Morgan:
In the words of one Homer Simpson....doh
Of course you are correct and it makes no sense to notifyAll in the lock().
I'd like to think I would have caught that during my review but then again....
Alan.
SCJP 1.4<br />SCWCD 1.3<br />SCJD<br />SCBCD<br />IBM Xml Cert in progress
public long lockRecord(final long recNo) { long cookie = //get the cookie as identifier try { //cookies is the hashmap to store the locked record. synchronized (cookies) { while (cookies.containsKey(new Long(recNo)) || cookies.containsKey(new Long(LOCK_DB))) { cookies.wait(); } cookies.put(new Long(recNo), new Long(cookie)); } } catch (InterruptedException e) { ////// } return cookie;}
The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
SCJP, SCJD, SCWCD, OCPJBCD
Originally posted by David Sham:
I just received my exam scores and somehow got a perfect score on the locking mechanism for my project(am still surprised). So Zee asked for my 2 cents.
From the code above, the only thing I can offer is that the synchronization occurs on a Hashtable object within the method. It is also within a try/catch block which catches an InterruptedException. From a maintainability standpoint, somebody could add additional code within the try/catch, but outside the synchronized block. This added code may not pertain to the enclosing try/catch block which would mean the try/catch block would be encompassing unrelated code. This could become difficult to maintain.
Another approach would be to just synchronize the entire method and only put in the method what needs to be synchronized. I did this in my solution. This way, I'm not calling wait() on the synchronized object, but on the executing thread intstead. My unlock method was also synchronized, and I just called notifyAll() on the executing thread there as well.
Now, there are really 2 parts to the locking mechanism that must be accounted for. One is tracking the holding client (the client holding the locked record) with the lock cookie used (assuming you are using lock cookies in your assignment). The other is tracking the lock cookie to the locked record. This is to ensure that the holding client accesses the correct record when performing an operation that requires locking. I used 2 Hashtables: 1 to track the holding client ID (a unique Integer value) and the lock cookie, and the other to hold the lock cookie and record number.
My solution used a timeout option in which the locking manager forced an unlock if a lock on a record timed out (after 30 seconds). This prevents thread deadlock from occuring.
Otherwise, who knows why people get the scores they do. I got a perfect score for locking, but got only 7/40 for network server.
Congratulations Zee on passing the certification. Don't let your locking score get to you. The important thing is that you're now an SCJD!!![]()
1. Why lock the whole DB ? (reference to LOCK_DB)
2. You say you keep a hashtable of Client ID and lockCookie to ensure that the holding client accesses the correct record when performing an operation that requires locking.
SCJP 1.4<br />SCWCD 1.3<br />SCJD<br />SCBCD<br />IBM Xml Cert in progress
SCJP 1.4<br />SCWCD 1.3<br />SCJD<br />SCBCD<br />IBM Xml Cert in progress
2. You say you keep a hashtable of Client ID and lockCookie to ensure that the holding client accesses the correct record when performing an operation that requires locking.
I'm a bit confused.
When I successfully lock a record I get back a lockCookie.
Now any methods that change the data must pass in a recordNum and the lockCookie. If they don't match then you can't do it.
I can't see why you need the second hashtable ?
Now, what is to prevent clientB from using lockCookie1 to work with or unlock record7?
BTW, locking the entire database is not necessary. You should only account for locking the record in question.
Ok but how does clientB get lockCookie1 ?
It does not matter how clientB gets lockCookie1. The fact that you are implementing a solution which would prevent this from happening adds another layer of security. Realistically, clientB should never get lockCookie1. But from a maintainability argument, you could say that by implementing this additional level of security (via a second Hashtable), clientB is prevented from executing a locked-record operation with the wrong lockCookie.
What about the case Zee mentioned where I have to reuse deleted records when creating new ones if possible.
clientA does a read() and figures that record 2 is deleted.
Meanwhile clientB goes and deletes record 1
ClientA creates a new record over record 2.
This is not a big deal really but to be correct they should have used record 1.
By locking the whole DB I can avoid this.
What am I missing here ?
I think you are missing the KISS principle! (Keep It Simple Stupid)Try to keep it as simple as possible. As long as you check to see if a record is deleted (to reuse it) when doing a create new record operation you should be fine.
One suggestion would be to synchronize the entire create new record operation and call a searchForDeletedRecord() method within that operation. If the create new record operation (or method) is synchronized then the executing thread cannot slice out mid-operation. Since it is synchronized, only 1 thread at a time can execute that operation. Therefore, the scenario you described should not occur. This is how I designed my solution.
However, this will not work if you are using multiple Data class instances with each instance using its own RandomAccessFile to read from and write to the database file. I had only 1 Data class and RAF in my solution (which resided in my RMI Remote Implementation object) - because of the requirement to use lockCookies.
I meant that the programmer had to develop code that interrupted the thread doing the locking - it could be argued that the programmer did this in a bad way.What you mean by "implemented the interrupt" ?
This sounds reasonable.In my locking manager I throw an IntException if a thread which is waiting is interrupted.
So in the other words I have a normal/default behavior and for extreme cases (interrupted cases) i throw exceptions.
Am I right ?
The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
When I said:
1. I have my wait() in a try catch(InterruptedException) so after interrupt the condition is checked again.
I wasn't 100% clear. What I meant is that my wait is in a try catch and the try catch is inside the while as so:
while (lockMap.containsKey(new Integer(recNo)))
{
try
{
lockMap.wait();
}
catch (InterruptedException inte){}
}
Will I still suffer from the problem you outlined ?
The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
clientA has lockCookie1 for record7
clientB has lockCookie2 for record7
SCJP 1.4<br />SCWCD 1.3<br />SCJD<br />SCBCD<br />IBM Xml Cert in progress
What you are showing here is a case where you are "swallowing" the exception - that is the exception disappears and is never seen again.
As for the lock DB. My create() method is already fully synchronized and I have only 1 Data instance.
But does this stop thread from clientA switching out half way thru create() and clientB running delete() to effectively change the ground under clientA's feet as it were ?
Originally posted by David Sham:
Wait, wait, wait!! Let me clarify something here. Just by synchronizing the create() method, this will not prevent a different thread from executing the delete() method.
If you have only 1 Data class and RandomAccessFile, then what needs to be synchronized is the read from and write to operations with the RAF. This is because if there is only 1 RAF and its operations are synchronized, then the executing method (create() or delete(), etc.) will have total control over the RAF for the during of the synchronized code enclosing the RAF. If the create() method is synchronized and it handles the RAF operations, then that should prevent a delete from occuring while the create method is executing.
But if the create() method does not handle the RAF operations to the database file, then simply synchronizing it will not prevent a delete() method operation from occuring on the file.
But is this not effectively the same as locking the DB ?
I mean when 1 client is creating in your app can another client be reading ?
Willie Smits can speak 40 languages. This tiny ad can speak only one:
a bit of art, as a gift, that will fit in a stocking
https://gardener-gift.com
|