aspose file tools*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes 44/80.....damn locking! Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "44/80.....damn locking!" Watch "44/80.....damn locking!" New topic
Author

44/80.....damn locking!

Kris Reid
Ranch Hand

Joined: Jan 05, 2005
Posts: 247
I just got my results back.
Not counting the 44/80.

I tested my Data class with multpile threads on multiple machines all competing for the same record. I even had 2 other programmers test it.

Does anyone want to volunteer to test my locking?
email me if your keen and I'll send you the code.

I'm dieing to know what is wrong with it!
Cleverson Schmidt
Ranch Hand

Joined: Feb 17, 2004
Posts: 55
Hi,

Could you explain what's your lock strategy? Maybe anyone here can give you a tip on what you have missed afterwards.
Kris Reid
Ranch Hand

Joined: Jan 05, 2005
Posts: 247
My locking is done with a hashmap the Thread is the key and the record number is the record. It is pretty simple.



Hope I am not vialating anything be posting to much code.
It doesn't work apparently so no one should copy it

Thanks

[Andrew: Yes, this much code does violate our rules for posting too much code. There are some issues with the method I have left, which if discussed in this topic, could result in someone getting a more complete solution.]

[Andrew: PS. Nice to see you using some of the Tiger features, but why didn't you use the new concurrency classes?]

[Andrew: PPS: Already late at night - I will post comments on your lock method tomorrow if others haven't beaten me to it]
[ March 22, 2005: Message edited by: Andrew Monkhouse ]
David Abramowicz
Ranch Hand

Joined: Dec 10, 2004
Posts: 56
How do you know the record hasn't been deleted while you were waiting?

/Dave
Paul Bourdeaux
Ranch Hand

Joined: May 24, 2004
Posts: 783
Hi Kris,

I don't see any type of notify in your code. How will waiting threads know when to wake up and try for the lock again?


“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
Cleverson Schmidt
Ranch Hand

Joined: Feb 17, 2004
Posts: 55
Paul,

I don't think it is necessary to use notifyAll on the lock method. What would be the advantage of waking up waiting threads which will not be able to aquire the lock? They would wake up and wait again right after realizing that the record is still locked.

notifyAll is indeed required on unlock, but there is no need to call it on lock.

Best Regards
Cleverson Schmidt
Cleverson Schmidt
Ranch Hand

Joined: Feb 17, 2004
Posts: 55
Kris,

Consider the following scenario:


Can your lock strategy handle this scenario flawlessly?

Best Regards
Cleverson Schmidt
Paul Truckle
Greenhorn

Joined: Feb 22, 2005
Posts: 24
Can I ask why it's necessary to use a HashMap that records the current Thread ? Why do we need the thread recorded ? Is there any benefit to this over using a HashSet and recording the record number as an Integer() ?

Thanks, Paul.
Tobbe Furn
Greenhorn

Joined: Mar 11, 2005
Posts: 1
Can you say it's the clients responsibility to always call the
lock() method before calling create(), update() or delete() ???
Paul Bourdeaux
Ranch Hand

Joined: May 24, 2004
Posts: 783
Can I ask why it's necessary to use a HashMap that records the current Thread ? Why do we need the thread recorded ? Is there any benefit to this over using a HashSet and recording the record number as an Integer() ?

You should have some way to ensure that the client that locked the record is the only client that is allowed to unlock the record. Otherwise, Thread a could lock record #123 and get ready to do some work on it, but before it can, Thread b unlocks record #123.

Many of the assignment versions specify a lockCookie in the interface. But for those that don't, as this one apparently does not, associating the Thread with the record number is a good way to go.
Paul Bourdeaux
Ranch Hand

Joined: May 24, 2004
Posts: 783
Actually, you need it in both. Because the HashMap locks is static, every instance of the Data class shares the same one. Any thread attempting to enter a synchronized block on this object will go into a waiting state if another thread has the exclusive lock on it. Feel free to correct me if I am wrong in this understanding. I am basing much of this from the Threading chapter in Max's book.


OK, I stand corrected on my earlier post. The thread would enter a blocked stated, not a waiting one, and therefore I don't think notifyAll is needed in the locking method. My Mistake!
peter wooster
Ranch Hand

Joined: Jun 13, 2004
Posts: 1033
Did you use RMI? If so there is no guarantee that the unlocking call is made on the same thread as the locking call. You must have a means such as a cookie or a Data instance that identifies the client session that locked the record. The thread is sufficient if you are using Sockets and each client has its own thread.
Andrew Monkhouse
author and jackaroo
Marshal Commander

Joined: Mar 28, 2003
Posts: 11460
    
  94

Hi Kris,

Two of the potential issues I was going to discuss have already been covered (specifically: handling deleted records, and using the thread to identify the client (cannot be done if using RMI)).

I strongly recommend against "swallowing exceptions" as you have done (just ignoring an exception). The only time I personally think this is acceptable is when the exception is expected. In all other cases you should either log it, or re-throw it, or both.

One other issue that is not covered in the code you posted (not even in the code I removed) is how did you handle two clients trying to call create() simultaneously?

Just FYI, an example (from some book due out in a few months) showing how the concurrency classes might be used (Note: this code uses timeouts which are almost certainly not allowable in your assignments: so don't use this sample):



Regards, Andrew


The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
Paul Bourdeaux
Ranch Hand

Joined: May 24, 2004
Posts: 783
Just FYI, an example (from some book due out in a few months)
Outstanding! I was wondering if a new book was going to be released with the advent of Java 5.0! Granted, I will have my SCJD by then (unless something goes horribly, horribly wrong), but I will still pick up a copy for reference if it is as good as the last one!

Sorry, I know it is off topic, but this is the first I heard of it!
Jeroen Wenting
Ranch Hand

Joined: Oct 12, 2000
Posts: 5093
Originally posted by Andrew Monkhouse:

I strongly recommend against "swallowing exceptions" as you have done (just ignoring an exception). The only time I personally think this is acceptable is when the exception is expected. In all other cases you should either log it, or re-throw it, or both.

Regards, Andrew


And in that case you should always document why you swallow it and why it's expected.


42
Anonymous
Ranch Hand

Joined: Nov 22, 2008
Posts: 18944
I don't mean to hijack this thread, but I've used an update check while an object is waiting for the lock. The update check will throw an update exception once the object has acquired the lock, if the record has been deleted, book or even modified while waiting for the lock.

Does this update check seem like overkill too much?
Frans Janssen
Ranch Hand

Joined: Dec 29, 2004
Posts: 357
Originally posted by Matt Garner:
I don't mean to hijack this thread, but I've used an update check while an object is waiting for the lock. The update check will throw an update exception once the object has acquired the lock, if the record has been deleted, book or even modified while waiting for the lock.

Does this update check seem like overkill too much?


Matt,

I think it is likely overkill. In case the record is deleted whilst waiting for the lock, you can (must!) throw RecordNotFoundException.

"Book" is a business action: I would be careful not to pollute your Data class with business logic!

Finally, I would consider it bad coding style to throw an exception in case there's not a problem. For example, if I lock a record and receive an (update) exception, I would assume that I was not granted the lock.

The better way to do it IMHO is to wait for the lock and once it is acquired, you can test if any special conditions exist, such as it being booked by another client.

Frans.


SCJP 1.4, SCJD
Anonymous
Ranch Hand

Joined: Nov 22, 2008
Posts: 18944
Hi Frans,

I was being drawn towards that conclusion as well. Your explanation has helped make my mind up.

Cheers,
Matt.
Kris Reid
Ranch Hand

Joined: Jan 05, 2005
Posts: 247
Hi Guys

Thanks for all the replys. I've been out of the office and just read them.

Cleverson

This does work as it will:
lock record number
try to do operation (delete, update, whatever) fail or succeed
unlock record number

Paul
I used a hasmap using a Thread as the key so that each Thread can only have one record locked and only that Thread can unlock the record.

peter
I did use RMI not sockets. It sounds like that is a problem?
wont the Thread that locks, updates, unlocks the record be the same one still?

Tobbe
I use the proxy pattern so the client doesn't have access to the Data class. The work with the proxy class which handles calls the lock/unlock methods.

Andrew
The Data class implements the singleton pattern and the create method is synchronized. Therefore one Thread will finish creating its record before another can start.


Thanks for all your comments. Can some one explain why it my locking technique wont work with RMI? It doesn't make sense to me.

[ March 28, 2005: Message edited by: Kris Reid ]
[ March 28, 2005: Message edited by: Kris Reid ]
Kris Reid
Ranch Hand

Joined: Jan 05, 2005
Posts: 247
Forgot to mention.
The remote/local client calls Proxy.Delete(5)

Each client has there own instance of the Proxy.
All Proxys share a singleton of Data.
The Proxy then calls:
Data.deletes(5)
(I never actually delete records just mark them as deleted. So it will just mark it as deleted again. I even added a method to restore records.)

Isn't this going to be the same thread calling these methods?
Therefore being the only Thread that can unlock the record?
Kris Reid
Ranch Hand

Joined: Jan 05, 2005
Posts: 247


With an Exception like this where it is unlikely that the exception will ever be throw and doesn't matter if it is throw what is the point of handling it? And how can you handle it?

This will simply continue in the loop check if the records is still locked if it is try an wait again. What is the problem with that?
peter wooster
Ranch Hand

Joined: Jun 13, 2004
Posts: 1033
Originally posted by Kris Reid:
...
peter
I did use RMI not sockets. It sounds like that is a problem?
wont the Thread that locks, updates, unlocks the record be the same one still?
...


It's the case that the thread that does the unlock is not necessarily the one that did the lock. You can build a test to prove it. As far as the 44/80, I didn't use the thread as a key and was aware of this problem, tested every case I could think of, and still got the 44/80 myself. I sent my code off to Max, who volunteered to look at it, but still haven't heard anything.
[ March 28, 2005: Message edited by: peter wooster ]
Kris Reid
Ranch Hand

Joined: Jan 05, 2005
Posts: 247
This is really bugging me. The one thing I was aiming for was to NOT get 44/80 on locking. I've sent mine to my old Uni lecturer. She has a Doctorate in Distributed Computing so she should be able to determine the presence or absence of a problem.

Peter do you mind sending me your locking code?
Sean Gildea
Ranch Hand

Joined: Jul 01, 2004
Posts: 81
Kris,

I got an 80/80 on my locking and I believe the main reason was because I chose to check that the record was not deleted before updating. I basically did 2 checks on the record before updating, the first before the wait and the second after it was released from waiting.
[ March 28, 2005: Message edited by: Sean Gildea ]

SCJD, SCBCD, SCJP
peter wooster
Ranch Hand

Joined: Jun 13, 2004
Posts: 1033
Originally posted by Sean Gildea:
Kris,

I got an 80/80 on my locking and I believe the main reason was because I chose to check that the record was not deleted before updating. I basically did 2 checks on the record before updating, the first before the wait and the second after it was released from waiting.

[ March 28, 2005: Message edited by: Sean Gildea ]


I check that the record is still valid after getting the lock, but not before. If the record is deleted the lock would be immediately obtained and then released because it wasn't a valid record. The check after is needed, but the one before does nothing.
Kris Reid
Ranch Hand

Joined: Jan 05, 2005
Posts: 247
My Uni Lecturer pointed out that in my unlock method I have

if (some condition)
unlock(record number)

it should be a while loop as you as you can't always unlock a reocrd
i.e. something might throw an exception so it should try again
peter wooster
Ranch Hand

Joined: Jun 13, 2004
Posts: 1033
Originally posted by Kris Reid:
My Uni Lecturer pointed out that in my unlock method I have

if (some condition)
unlock(record number)

it should be a while loop as you as you can't always unlock a reocrd
i.e. something might throw an exception so it should try again


I don't know what would throw a non fatal exception in the unlocking code. All my (and I assume your) unlock does is {synch; remove record from map; notifyAll}. The only code there that throws anything is notifyAll and only if you don't own the object's monitor.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: 44/80.....damn locking!