aspose file tools*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes Multiple lock requests on the same record number 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 "Multiple lock requests on the same record number" Watch "Multiple lock requests on the same record number" New topic
Author

Multiple lock requests on the same record number

Jeff Philp
Greenhorn

Joined: Jun 04, 2011
Posts: 12
Hi All,

This is my first post, and firstly I just want to think Roel, Roberto, and Andrew for their consistently high caliber of replies. It has made working on this OCMJD project so much less daunting.

I am currently working on the Data class, and thinking about the the locking. I have tried searching through for the forums relating to multiple record locking etc., but I have not seen any topic cover the subject of a client trying to lock the same record multiple times.

e.g.


Now for assignments which do not have a lock cookie its implied that the locking mechanism is aware of which client is locking the record, so it could easily detect multiple lock attempts on the same record and just return from the lock() method call. But my assignment has a lock cookie, which doesn't at first glimpse require me to track the client who locked the record as I can rely on them to pass the lock cookie when they are updating / deleting etc. If a single thread attempted calling lock on the same record multiple times, on locking code which was unaware of the calling client then it would deadlock waiting for the record to be released which would never happen.

My question is:
a) Should I handle this situation? Which would require my code to be aware of which client is attempting the lock.
b) and if I don't handle it, I can add this requirement to the Data Javadoc stating that the client must only lock one record at a time, and not make multiple attempts to lock the same record once the lock has been obtained?

I suppose if I should handle this situation, then the locking code needs to become aware of the locking cookie, and of which client is trying to get the lock.

Any thoughts would be much appreciated
Sean Keane
Ranch Hand

Joined: Nov 03, 2010
Posts: 581

Hi Jeff. This thread here sounds similar to the issue you mentioned. This guy ignores multiple requests by a client to lock a record that it already holds the lock for:

[edit] do not post complete code snippets

But he mentions his lock method is defined as follows, so it's not clear to me how his lock method could know if a client already holds a lock on a particular record...


SCJP (1.4 | 5.0), OCJP (6.0), OCMJD
Jeff Philp
Greenhorn

Joined: Jun 04, 2011
Posts: 12
Hi Sean,

Thanks for your reply. Your right he does seem to be tracking the client and can cope with multiple requests for the same record. His code must be doing something similar to people whose projects do not include a lock cookie, and therefore have to have a way of identifying the client.

So there is at least one person in the same situation as me who has chosen to handle this situation, rather than just writing it into the API javadoc.
Ryan Small
Greenhorn

Joined: Jun 09, 2011
Posts: 3

Sean Keane wrote:
so it's not clear to me how his lock method could know if a client already holds a lock on a particular record...


A common scheme I've seen is to use the thread's ID.
Sean Keane
Ranch Hand

Joined: Nov 03, 2010
Posts: 581

Ryan Small wrote:
Sean Keane wrote:
so it's not clear to me how his lock method could know if a client already holds a lock on a particular record...


A common scheme I've seen is to use the thread's ID.


Yep, I saw that solution somewhere. But this does work in the context of using RMI?

Maybe someone with more knowledge of RMI can comment, but my understanding was that you could not guarantee clients requests would always run in the same thread. Therefore you can't rely on Thread.currentThread.getId() to identify a client when using RMI.

  • Client-A could call lock() once and on the server side Thread-1 would execute the request.
  • Then client-A could call lock() once again but a different thread Thread-2 may handle the requests - i.e. there's no guarantee that Thread-1 would handle this second request from client-A.

  • Also, if RMI is pooling threads then Thread-1 may actually be a totally different client altogether, which would be another reason why you can't rely on Thread.currentThread.getId() to identify a client.
    Dennis Grimbergen
    Ranch Hand

    Joined: Nov 04, 2009
    Posts: 142

    Sean Keane wrote:But this does work in the context of using RMI?

    No, this does not work with RMI.
    Sean Keane wrote:
    Maybe someone with more knowledge of RMI can comment, but my understanding was that you could not guarantee clients requests would always run in the same thread. Therefore you can't rely on Thread.currentThread.getId() to identify a client when using RMI.

    I'm an RMI noob, but your statement seems correct..

    I didn't have this problem. I used sockets


    SCJP, SCWCD, SCJD
    Sean Keane
    Ranch Hand

    Joined: Nov 03, 2010
    Posts: 581

    After some further reading it seems that the RMI Factory pattern would allow you to uniquely identify a client by the thread.

    I've yet to look into this solution in more detail but Andrew mentions this solution in his book - so I'm guessing it does work.

    However, Andrew mentions it because he is not returning a cookie from his lock() method.

    My lock() method is returning a cookie value so this seems a little confusing to me! At the moment I simply generate the cookie value using System.nanoTime(). Also, I don't check if a client has already locked the record because I have no way of checking this in my current implementation.

    So if am understanding this correctly, then I should implement the RMI Factory solution, and inside my lock() method I should use Thread.currentThread.getId() as the cookie value. Then I can add a check to my lock method to see if the record being locked is already locked by Thread.currentThread.getId().

    Is this a commonly followed approach? Are people really handling multiple calls to lock(), without a call to unlock() in between, by the same client? Or merely documenting that you shouldn't make multiple calls to lock() on the same record without calling unlock() after each lock()?
    Roel De Nijs
    Bartender

    Joined: Jul 19, 2004
    Posts: 5389
        
      13

    First of all, you have interfaces with a lockCookie and other ones without. I had an interface without a lockCookie and then you perfectly know which client has locked which record. Interfaces with a lockCookie (like the one you have) can't know that. Although you didn't find any threads concerning this issue, a lot of threads have discussed this already
    You could of course code a work-around and implement a similar system to the one people without a lockCookie in the interface implemented to identify the clients, but that would make the lockCookie quiet useless. So the majority (if not all) of the people (who have thought about this situation) have mentioned this (and thus that it's important to unlock a record before locking another one) in their choices.txt and/or in javadoc.

    Secondly, using the id of the current thread will only work in standalone mode, not in networking mode if you decide to use RMI as your networking protocol. Simply because (as already mentioned by Sean Keane) consecutive requests from the same client are not guaranteed to be handled by the same thread (and that's one of the drawbacks about RMI).


    SCJA, SCJP (1.4 | 5.0 | 6.0), SCJD
    http://www.javaroe.be/
    Sean Keane
    Ranch Hand

    Joined: Nov 03, 2010
    Posts: 581

    Roel De Nijs wrote:You could of course code a work-around and implement a similar system to the one people without a lockCookie in the interface implemented to identify the clients, but that would make the lockCookie quiet useless.


    This was my initial reaction - that identifying the client in some other manner would renderer my lock cookie to be useless, or I'd have two ways of identifying a client, which to me would be bad design.

    But what if people with the lock cookie were to do the following:

    1) In standalone mode - assign the Thread ID to the lockCookie.
    2) In network mode (using RMI) - use the RMI Factory to uniquely identify the client and assign this value to the lockCookie.

    So basically copy the solution used by people who didn't have a lockCookie, but simply assign the value you generate to the lockCookie.

    I've read some other threads from people who had no lock cookie and how they handled this problem, but I still don't understand fully how in network mode they checked inside the lock-method whether a client had already lock the record.

    Jeff Philp
    Greenhorn

    Joined: Jun 04, 2011
    Posts: 12
    Hi guys,

    Thank you all for your replies, its much appreciated

    I think I will just document the usage of the API in the Javadoc and explain why in my choices.txt as it will show that I have thought of a situation where if a client calls the same lock method twice with the same record number, and its using a single thread that it could get stuck there.

    Roel, I am sure you are quite correct in this discussion being had before, and I am ashamed to admit how many pages of threads I have read on locking over the past few months. I probably just missed this discussion
    Sean Keane
    Ranch Hand

    Joined: Nov 03, 2010
    Posts: 581

    It sounds like the simplest and most straight forward approach is to document how your API works and document in your choices.txt that you have thought about this problem.

    However, I'd still like to understand fully how people solve this problem. Any threads I've read seem to be a bit confusing and it's hard to understand how people solved it.

    It seems people used different approaches. Some used the RMI Factory approach, some used another approach.

    I had a brief read of the RMI approach, and I could have picked it up wrong, but from what I read you seem to return a separate instance of the Data class for each client. I'm not sure how that would fit in with my design of making the Data class a singleton and using a business service with a thin client.

    I read a thread here where Roel had this setup:

    But I don't see how this stops the client with id of 999 calling the lock method a second time?

    Also, am I right in understanding that this solution happens at the Business layer? So you aren't actually preventing the situation we are talking about here - someone can still call your lock method multiple times?

    It seems you still have to document something along the lines of "you must call setClientID() before calling lock()"...which really doesn't give you anything over documenting "you must call unlock() after lock() on a record before calling lock() on that same record again". In both situations you are expecting the user of your API to read your documentation and understand it...i.e. they can't blindly call lock().
    Roel De Nijs
    Bartender

    Joined: Jul 19, 2004
    Posts: 5389
        
      13

    Sean Keane wrote:But I don't see how this stops the client with id of 999 calling the lock method a second time?

    It doesn't stop the client from calling lock method a second time, but nothing will. But my code will prevent a client from locking a record twice or locking multiple records at the same time (if the API is used correctly)
    Sean Keane
    Ranch Hand

    Joined: Nov 03, 2010
    Posts: 581

    Roel De Nijs wrote:
    Sean Keane wrote:But I don't see how this stops the client with id of 999 calling the lock method a second time?

    It doesn't stop the client from calling lock method a second time, but nothing will. But my code will prevent a client from locking a record twice or locking multiple records at the same time (if the API is used correctly)


    I don't understand how your code prevents a client from locking the a record twice. How does this actually work?

    If I simply take your Data class (not your Business Service class) and I call the lock-method twice, what prevents me from locking it twice?
    Roel De Nijs
    Bartender

    Joined: Jul 19, 2004
    Posts: 5389
        
      13

    Sean Keane wrote:If I simply take your Data class (not your Business Service class) and I call the lock-method twice, what prevents me from locking it twice?

    Like I already mentioned in my previous post, it all depends on good API usage. So if you decide in a multi-threaded environment to just invoke the lock-method a few times, you won't be able to do that (and your stuck in the same situation as the lockCookie-interfaces). If you use the API correctly (identifying the client/thread before a given set of methods), you'll get an IllegalStateException when you try to lock more than 1 record at a time
    Sean Keane
    Ranch Hand

    Joined: Nov 03, 2010
    Posts: 581

    Roel De Nijs wrote:So if you decide in a multi-threaded environment to just invoke the lock-method a few times, you won't be able to do that (and your stuck in the same situation as the lockCookie-interfaces).

    Ok, so in concrete terms, the piece of code below will behave exactly the same in your application and in mine. They will both wait forever:
    Is my understanding correct here?
    Roel De Nijs wrote:If you use the API correctly (identifying the client/thread before a given set of methods), you'll get an IllegalStateException when you try to lock more than 1 record at a time

    Nice. I like the fact that I'll get an IllegalStateException. I dislike the fact that I have to make another method call.

    So, one thing I'm curious about this, why didn't you throw an IllegalStateException I the unlock-method is called without the client id being set in advance?
    Roel De Nijs
    Bartender

    Joined: Jul 19, 2004
    Posts: 5389
        
      13

    Sean Keane wrote:Is my understanding correct here?

    Yes.

    Sean Keane wrote:So, one thing I'm curious about this, why didn't you throw an IllegalStateException I the unlock-method is called without the client id being set in advance?

    Don't understand what you exactly mean, there is something weird about that sentence.
    Sean Keane
    Ranch Hand

    Joined: Nov 03, 2010
    Posts: 581

    Roel De Nijs wrote:
    Sean Keane wrote:So, one thing I'm curious about this, why didn't you throw an IllegalStateException I the unlock-method is called without the client id being set in advance?

    Don't understand what you exactly mean, there is something weird about that sentence.

    Typos

    Why didn't you throw an IllegalStateException when the lock-method is called without the client id being set in advance?
    Roel De Nijs
    Bartender

    Joined: Jul 19, 2004
    Posts: 5389
        
      13

    Sean Keane wrote:Why didn't you throw an IllegalStateException when the lock-method is called without the client id being set in advance?

    Ah, now I understand and that's an easy one: you only have to set the client id when you work in a multi-threaded environment.
    Sean Keane
    Ranch Hand

    Joined: Nov 03, 2010
    Posts: 581

    Roel De Nijs wrote:
    Sean Keane wrote:Why didn't you throw an IllegalStateException when the lock-method is called without the client id being set in advance?

    Ah, now I understand and that's an easy one: you only have to set the client id when you work in a multi-threaded environment.


    That makes sense, thanks!

    I guess you could have required the client-id be set in both local and server mode, just for the sake of consistency and only having one way for someone to perform a certain action in your API. On the flip side, you are making them do something that is not necessary when they are doing it in local mode.
    Roel De Nijs
    Bartender

    Joined: Jul 19, 2004
    Posts: 5389
        
      13

    My previous explanation was not 100% complete. This is the full version: you only have to set the client id when you work in a multi-threaded environment where you don't have the guarantee that consecutive calls by a client are not handled by the same thread (like with RMI).
    Sean Keane
    Ranch Hand

    Joined: Nov 03, 2010
    Posts: 581

    Roel De Nijs wrote:My previous explanation was not 100% complete. This is the full version: you only have to set the client id when you work in a multi-threaded environment where you don't have the guarantee that consecutive calls by a client are not handled by the same thread (like with RMI).


    How is that different to your original explanation?

    You only set the client id on the data class when running in server mode - that's what I understood from your first explanation and I understand the same from this explanation also?
    Roel De Nijs
    Bartender

    Joined: Jul 19, 2004
    Posts: 5389
        
      13

    Sean Keane wrote:How is that different to your original explanation?

    The extra part (where you don't have the guarantee that consecutive calls by a client are not handled by the same thread) is the different. If you have a multi-threaded environment where each request of a client is handled by the same thread you don't have to set the client-id. Of course with regard to our assignment, the extra part makes no difference (because of the RMI).
    Sean Keane
    Ranch Hand

    Joined: Nov 03, 2010
    Posts: 581

    Roel De Nijs wrote:If you have a multi-threaded environment where each request of a client is handled by the same thread you don't have to set the client-id.


    So in concrete terms what happens if your Data class is used in a multi-threaded environment where each request of a client is handled by the same thread?

    You are saying that the client-id does not have to be set in this context. So what happens inside your lock method? Are you doing a check inside the lock-method to see if the client-id is set, and if it is not set then you are assuming that you can identify a client by the ID of the thread?




    Roel De Nijs
    Bartender

    Joined: Jul 19, 2004
    Posts: 5389
        
      13

    Sean Keane wrote:Are you doing a check inside the lock-method to see if the client-id is set, and if it is not set then you are assuming that you can identify a client by the ID of the thread?

    Almost correct. This logic is of course in another method and is called from the lock-method.
    Jonathan Elkharrat
    Ranch Hand

    Joined: Dec 31, 2008
    Posts: 170

    i didn't read all the posts but i want to make few things clear:

    1. there was not any requirement to implement a Reentrant lock!

    2. yes, if someone call twice the lock he'll be deadlocked. just like the next case:



    but thanks for the notice, i'll mention in my choices.txt and the javadoc that the lock
    isn't re-entrant...


    as you can see, even in the java SE API there's a Lock interface and a ReentrantLock
    that inherit from it.

    from the Lock javadoc:
    A Lock class can also provide behavior and semantics that is quite different from that of the implicit monitor lock, such as guaranteed ordering, non-reentrant usage, or deadlock detection. If an implementation provides such specialized semantics then the implementation must document those semantics.


    SCJP 5, SCWCD 5, SCBCD 5
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: Multiple lock requests on the same record number