• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

44/80.....damn locking!

 
Ranch Hand
Posts: 247
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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!
 
Ranch Hand
Posts: 55
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 247
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ]
 
Ranch Hand
Posts: 56
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
How do you know the record hasn't been deleted while you were waiting?

/Dave
 
Ranch Hand
Posts: 783
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?
 
Cleverson Schmidt
Ranch Hand
Posts: 55
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 55
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Kris,

Consider the following scenario:


Can your lock strategy handle this scenario flawlessly?

Best Regards
Cleverson Schmidt
 
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Can you say it's the clients responsibility to always call the
lock() method before calling create(), update() or delete() ???
 
Paul Bourdeaux
Ranch Hand
Posts: 783
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 783
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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!
 
Ranch Hand
Posts: 1033
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
author and jackaroo
Posts: 12200
280
Mac IntelliJ IDE Firefox Browser Oracle C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Paul Bourdeaux
Ranch Hand
Posts: 783
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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!
 
Ranch Hand
Posts: 5093
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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.
 
Ranch Hand
Posts: 18944
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?
 
Ranch Hand
Posts: 357
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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.
 
Anonymous
Ranch Hand
Posts: 18944
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 247
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 247
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 247
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


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
Posts: 1033
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 247
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?
 
Ranch Hand
Posts: 81
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ]
 
peter wooster
Ranch Hand
Posts: 1033
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 247
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 1033
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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.
 
reply
    Bookmark Topic Watch Topic
  • New Topic