aspose file tools*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes clarification about locking and cookie value 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 "clarification about locking and cookie value" Watch "clarification about locking and cookie value" New topic
Author

clarification about locking and cookie value

Yu Sun
Greenhorn

Joined: Nov 06, 2006
Posts: 29
Hi guys,

I have been reading the posts about locking for a while, and I have got the basic idea. I just want to clarify one thing and ask one question:

In lock() / unlock(), we need to generate a cookie value and put it together with the recNo in the lock map; In Update() / Delete(), we need to check if the current record is being locked, as well as if this current record is being lock by the same client thread. Correct?

If this is correct, then Question:

Why do we usually use System.currentTimeMillis(), or nanoTime()? In other words, how such a timing value can be used to identify a client thread? If we use Thread.getId(), I can understand. But if we use System.currentTimeMillis(), that means that we will store this value in the client class as an attribute after generating it, right?

Thanks.

Yu
Raf Szczypiorski
Ranch Hand

Joined: Aug 21, 2008
Posts: 383
You generate the cookie and give it to the client. The client has to remember it and use it if he subsequently want to update / delete the record, by passing it as a parameter. This means that if some other client guessed the cookie, it could also update / delete the record.
If you use RMI for your server communication, remember that you cannot rely on the same thread to always serve the same client - it might be different every single request.
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5597
    
  15

Hi Yu,

Only the lock-method will generate a cookie. This cookie must be used by the update, delete and unlock method, so you can guarantee that a record can't be updated, deleted and unlocked by another client than the one that has locked the record. So any value will be fine, but the more unique, the better of course:
  • always returning 5 for example doesn't give any guarantee, so that is not an appropriate one
  • System.currentTimeMillis() or System.nanoTime() will generate unique values
  • another possibility would be a number that increments by 1 each time, access and modification of this number should occur thread-safe of course
  • just using the record number is also possible and is already discussed here


  • I used the (easy and simple) System.nanoTime(), its uniqueness is more than enough for this assignment (and can easily be changed or enhanced in future releases of the application)

    Hope it helps!
    Kind regards,
    Roel


    SCJA, SCJP (1.4 | 5.0 | 6.0), SCJD
    http://www.javaroe.be/
    Yu Sun
    Greenhorn

    Joined: Nov 06, 2006
    Posts: 29
    Thanks Roel and Raf. Now I understand what kind value can be used.

    Now, I just want to confirm that after we generate the value in the lock method, we need to store it not only in the lock hashtable or map, but also in the client, right? If so, the client, the lock manager and the update() / delete() methods would probably need to communicate with each other, what is the common design on this?

    Specifically
    - after we generate the value in lock(), how and where to store it in the client, GUIController?
    - if we want to check whether the record is being locked by a certain client in update() / delete(), how to access the current client's value?

    I checked a lot of post, but did not find what I want. Thanks a lot.

    Yu
    Roel De Nijs
    Bartender

    Joined: Jul 19, 2004
    Posts: 5597
        
      15

    Hi Yu,

    On the server you will have a map which keeps track of the locked records, so you store record numbers with the generated cookies.

    On the client you store the cookie in a local variable, the process of updating a record will look like this:

    Kind regards,
    Roel
    Yu Sun
    Greenhorn

    Joined: Nov 06, 2006
    Posts: 29
    Thanks Roel. The code sample you gave makes sense. However, the lock() in my Data interface does not return any value. And obviously the update() method does not have the third parameter in the interface. How should we handle this?

    Yu
    Roel De Nijs
    Bartender

    Joined: Jul 19, 2004
    Posts: 5597
        
      15

    Hi Yu,

    So you say in your first post that lock method should generate a cookie value, but your interface doesn't use cookie values

    As you can see here there are many assignment versions. You are not required to generate a cookie value, you just have to think of a way to identify each client. You can't use RMI for that because it doesn't give you the guarantee that consecutive requests of 1 client will always be handled by the same thread.

    How should we handle this?
    That's completely up to you and depends on the approach you will follow (thin vs thick client). You can generate a unique client identification number (the approach I followed, use search engine with setClientId for more information), you could use sockets as networking protocol, use the RMI factory pattern (as described in andrew's book) and so on

    Kind regards,
    Roel
    Yu Sun
    Greenhorn

    Joined: Nov 06, 2006
    Posts: 29
    Sorry Roel. My description is a little bit unclear. Maybe there are too many things to consider about locking and I got confused.

    I just checked more posts, and getting a little bit better. However, let me ask a question directly on this code from here



    Now I understand both synchronized(data) parts in the beginning and the end. But what about the // Do work part?

    I think it should be:



    correct?

    If this is correct, in the update() method, we should also check in a way something like this:


    My question is: we execute data.setClientId(null) after the locking, how could Data read the clientId again when it execute the update() method? Should I do something like this in // Do work part: ?



    Thanks again.

    Yu
    Roel De Nijs
    Bartender

    Joined: Jul 19, 2004
    Posts: 5597
        
      15

    Hi Yu,

    Now I understand both synchronized(data) parts in the beginning and the end.

    If you really understand these parts, you'll know exactly what the "do work" part should be (for updating a record). And you'll also know why the 3 calls (could also done with the first 2, setting clientId back to null is not needed) must be performed as an atomic operation.
    If you don't understand these parts, you'll have to think further about these parts and the purpose of the setClientId (identifying a client). Making your Data class (and RMI implementation) thread-safe is the hardest part of the assignment and requires complete knowledge about threads, thread-safety and how RMI works. So that's why I just give you a hint about how you could solve it, but I feel you don't get the complete picture and are just guessing about the implementation details (without actually knowing why it is coded that way). And that's not the intention of this assignment: we are here to help people to clarify doubts, give them a hint or two to solve their issues,... but not to give you a complete solution.

    Kind regards,
    Roel
    Yu Sun
    Greenhorn

    Joined: Nov 06, 2006
    Posts: 29
    Hi Roel,

    Thanks a lot for your direction. I spent another day working on my locking. And finally I got my code passed the Robert's testing program. I was actually writing last post to confirm some of my understanding. I had some thoughts in mind, but just not 100% sure, so I tried to take advantage of you to confirm my understanding, which is not very good as you mentioned

    Later, I checked some more references and tested the code a lot, and I confirmed my understanding by experiments. I applied your approach of considering setting client Id and lock / unlcok / update as an atomic operation, which works well.

    Here is one more issue I want to confirm with you:
    - when using the Robert's test program, I replaced the lock() / update() / unlock() with synchronized { setId(); lock() / update() / update() } blocks, and got the correct results, I think this change is reasonable according to our design, right?
    - however, I am just concerned that whether this will pass Sun's automatic test. What if they don't use synchronized { } block with setting Id to test the lock() / update() / unlock(), although it will still work with a singal default clientId.

    Thanks again.

    Yu
    Roel De Nijs
    Bartender

    Joined: Jul 19, 2004
    Posts: 5597
        
      15

    Hi Yu,

    If you make an atomic operation of the complete update process like

    you will fail I guess (or might loose a significant amount of points). Because your application is simply not multithreaded: no other thread can swoop in between lock and update, or update and unlock. So your output would always be something like:

    thread1 locks record 1
    thread1 updates record 1
    thread1 unlocks record 1
    thread2 locks record 2
    thread2 updates record 2
    thread2 unlocks record 2
    And it will be each time the same output (maybe thread2 before thread1 once and again)

    In a multi-threaded application your output should be not predictable (you should know from your SCJP certification):

    thread1 locks record 1
    thread2 locks record 2
    thread2 updates record 2
    thread1 updates record 1
    thread2 unlocks record 2
    thread1 unlocks record 1

    This output could be possible, but if you run it again it can (and will) be completely different.

    That's why I only have an atomic operation for locking (setId, lock), and another atomic operation for updating (setId, update) and again another one for unlocking (setId, unlock). Between these atomic operations another thread can also lock another record or the same one (and has to wait), or update/delete, ... And this should also make clear why for example (setId, lock) must be an atomic operation.

    Kind regards,
    Roel
    Yu Sun
    Greenhorn

    Joined: Nov 06, 2006
    Posts: 29
    Hi Roel,

    I did three separated synchronized blocks as you did, so trust me that I understand your design correctly this time.

    I printed out the lock table when running Robert's test program, and you can see that in the middle, multiple locks are in the table; you can also find that some other thread will start locking another record before one thread trying to update or unlock a certain record; another proof is that if we do not check the rec validity twice, we might incorrect try to lock an deleted record.

    So you mean this (using synchronized atomic block) will be ok for Sun's test, right? And for the standalone version, we can just use the same version of Data and provide an Id, or we do not even use lock / unlock in the standalone version?

    Thanks.

    Yu

    Roel De Nijs
    Bartender

    Joined: Jul 19, 2004
    Posts: 5597
        
      15

    If you have 3 seperate synchronized blocks, you'll be fine. But I can't know you did, if you post something like this
    Yu Sun wrote:synchronized { setId(); lock() / update() / unlock() } blocks
    Seems to me you set the client id once and then have calls to methods lock, update and unlock, all in 1 atomic operation.

    I used the same Data class and used instead of the unique client id, just the thread id. According to my instructions a record should be locked prior to updating or deleting, so not using lock/unlock won't be an option (in my opinion).

    Kind regards,
    Roel
    Yu Sun
    Greenhorn

    Joined: Nov 06, 2006
    Posts: 29
    That confusing expression was my bad.

    Thanks again for you patience, Roel.

    Yu
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: clarification about locking and cookie value