• 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

Locks without Client IDs?

 
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
I am just about done with my project. I used RMI and modified the lock signatures to accomodate a client ID. What I still don't understand is the folks who managed to do locking without using a client ID. Could someone explain--in detail--how locks without client IDs work, and how it is possible for them to meet the requirement that only the client who locked a record can unlock it?
Thanks for you indulgence.
 
Ranch Hand
Posts: 164
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You can't meet the requirement without using a ClientID (a well-behaved client shouldn't even try to unlock a lock it doesn't own, needless to say).
A more important reason for using a ClientID is so that, if a client dies while holding a lock, the server can free the lock.
 
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You can lock a client based on Thread id(or Thread), if each client has their own Thread. How do you make sure that clients have their own thread? You supply one to each, using an RMI factory pattern, as shown here
All best,
M, author
The Sun Certified Java Developer Exam with J2SE 1.4
 
Ranch Hand
Posts: 62
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Tom,
Here is how I handled the situation. First you create a RMI connection factory class. Lets call it RMIConnectionFactory. This class should extend java.rmi.server.UnicastRemoteObject and implement java.rmi.Remote interface. In this class you have an instance of your Data class. This will be passed to all of your remote implementation objects that you create and return. For this you will have one method, lets call the method getRemoteObject(). This method should return your remote implementation that you will create back to the client. And that�s pretty much it; you have a unique instance (ID) for each client.
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Nicely done Rama. This is exactly the approach detailed in the link given above.
All best,
M, author
The Sun Certified Java Developer Exam with J2SE 1.4
[ November 19, 2002: Message edited by: Max Habibi ]
 
author
Posts: 3252
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Max Habibi:
You can lock a client based on Thread id(or Thread), if each client has their own Thread.

Yikes. I hope you meant to say "Object" where you said "Thread". If not, I would contend that this is a really suboptimal solution. Threads are really heavyweight in terms of creation time and system resource consumption. You can achieve the same thing simply by giving each client its own server-side Connection object to talk to, again using the Factory pattern. As said above, the object itself is the ID you are looking for.
- Peter
[ November 20, 2002: Message edited by: Peter den Haan ]
 
Peter den Haan
author
Posts: 3252
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I should probably add that I once was bartender here and have broadly seen three approaches taken:
  • Use a Factory creating a per-client Connection object.
  • Modify the signatures of lock() and unlock() to accomodate a client ID.
  • Ignore the requirements about the desired behaviour of lock() and unlock() and don't worry about client identity at all.
  • I have seen people pass with any of these approaches. Yes, that includes the third one, although their scores obviously weren't stellar.
    - Peter
     
    Max Habibi
    town drunk
    ( and author)
    Posts: 4118
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by Peter den Haan:
    Yikes. I hope you meant to say "Object" where you said "Thread".



    Hi Peter, I've enjoyed your posts here.
    No, I meant Thread: Remember, the only thing that gets stored in a map is a reference, not a whole new object: I can provide an example to demonstrate this if you like.
    So ok, even if it's just the Thread, why do it? Wouldn't the thread Id work just as well? No it wouldn't, because thread ID's are not guaranteed to be unique(and making them unique is not materially different from setting a client id).
    An interesting approach taken by one of my students was to use a
    WeahHasMap to store the Thread-lock combination. That way, if the thread was prematurely released, then the lock would eventually be released as well.
    All best,
    M, author
    The Sun Certified Java Developer Exam with J2SE 1.4
     
    Ranch Hand
    Posts: 186
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Hi, Max
    Regarding the WeakHashMap, I have a concern. Since the removal of the entry is automatically done, or to say somewhat unpredictable, how is it achieved that those suspending threads waiting for the very lock being notified?
    Regards
    James
     
    Ranch Hand
    Posts: 86
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I implemented lock without clientID.
    I think it meets the requirment.
    In my requirment, about lock:
    *********************************
    ...
    However, if two clients attempt to perform the sequence lock, read, modify, write, unlock concurrently, then both modification attempts will be handled correctly. The aim is to ensure that if two customers attempt to book a seat on the same flight concurrently, then the number of available seats is definitely reduced by two, unless there was only one seat, in which case, one customer will be advised at booking time that no more seats are available.
    ...
    *********************************
    I think the operation sequence lock,read,modify,write,unlock is just the action of book. The book function should be putted in anthor class for keeping Data general using.
    So the aim of lock is that blocking the book operation while the record is locked by anthor client for booking. You can see for this aim, clientID is unnecessary, and the container of locked record number is needed.
    In this way, How to deal with the exception of client dying? I putted the book action into a server end class.
    And another reason why shouldn't keep clientID is that the signature of lock , unlock shouldn't be change.
    That's all.
     
    Peter den Haan
    author
    Posts: 3252
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by Max Habibi:
    No, I meant Thread: Remember, the only thing that gets stored in a map is a reference

    No argument with that. The point is, if I understand you correctly, this solution needs a server-side Thread for every client, whereas you can achieve the same thing with a similar approach that needs just a single stateless server-side Object per client. This is both simpler and considerably more lightweight.
    Please correct me if I misunderstood the solution you propose.

    An interesting approach taken by one of my students was to use a
    WeahHasMap to store the Thread-lock combination. That way, if the thread was prematurely released, then the lock would eventually be released as well.

    If you supply every client with a server-side Connection object, you can implement the RMI Unreferenced interface to clean up locks after dead or sloppy clients with literally three lines of code. The nice thing is that it is completely predictable, since it relies on RMI leases under the hood and not on the the garbage collector.
    - Peter
    [ November 21, 2002: Message edited by: Peter den Haan ]
     
    Peter den Haan
    author
    Posts: 3252
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by HiBob Chu:
    You can see for this aim [of achieving proper handling of concurrent bookings using locks], clientID is unnecessary, and the container of locked record number is needed.

    That is correct. However, there is an additional requirement hidden in the javadoc for unlock() (at least that's where it was in my assignment) that in most implementations requires a client ID of some sort.

    In this way, How to deal with the exception of client dying?

    Although it is a Good Thing to handle this situation, I'm not sure you will be penalised if you don't.

    I putted the book action into a server end class.

    There's a problem with this. This presumably means that your server code is tied to the Fly By Night application, which significantly reduces its reusability. And reusability is one of your design goals.
    Ideally, you would come up with a networked, multi-user layer on top of the basic Data class which is as generic as Data itself.

    And another reason why shouldn't keep clientID is that the signature of lock , unlock shouldn't be change.

    You can change the signature, if you have a very good reason to. Of course you should clearly document this design decision.
    You can however implement a client ID scheme without changing the lock() and unlock() signatures.
    - Peter
     
    Max Habibi
    town drunk
    ( and author)
    Posts: 4118
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by James Du:
    Hi, Max
    Regarding the WeakHashMap, I have a concern. Since the removal of the entry is automatically done, or to say somewhat unpredictable, how is it achieved that those suspending threads waiting for the very lock being notified?
    Regards
    James


    when the lock is freed, then the condition that those threads are waiting on(that is, the record number not being in the map), is no longer true, and those Threads will be able compete for the lock naturally.
    HTH,
    M, author
    The Sun Certified Java Developer Exam with J2SE 1.4
     
    Max Habibi
    town drunk
    ( and author)
    Posts: 4118
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    No argument with that. The point is, if I understand you correctly, this solution needs a server-side Thread for every client, whereas you can achieve the same thing with a similar approach that needs just a single stateless server-side Object per client. This is both simpler and considerably more lightweight.


    I'm not sure I'm explaining myself well. There's already a server side Thread for each client, given the nature of the RMI factory. You're simply using that Thread, as opposed to walking around it.
    IMO, this is much simpler, and equally lightweight: After all, a reference to an Object that happens to be a Thread is no more espensive then a reference to any other Object. It's actually a much more intuitive compatibility between how Threads work.


    If you supply every client with a server-side Connection object, you can implement the RMI Unreferenced interface to clean up locks after dead or sloppy clients with literally three lines of code. The nice thing is that it is completely predictable, since it relies on RMI leases under the hood and not on the the garbage collector.


    I think we're talking about different things here. The solution you're proposing, while it would clean up remote objects, wouldn't have anything to do with releasing the locks held by those objects. That's the issue that the weakHashMap addresses, and the one that(I think) the original poster was asking about.
    All best,
    M, author
    The Sun Certified Java Developer Exam with J2SE 1.4
     
    Max Habibi
    town drunk
    ( and author)
    Posts: 4118
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Hi HiBob,
    I like your solution. As I explain in my book, Java developers have been elegently solving the SCJD for years: There's no reason to resort to signature changes.
    All best,
    M, author
    The Sun Certified Java Developer Exam with J2SE 1.4
     
    Peter den Haan
    author
    Posts: 3252
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by Max Habibi:
    I'm not sure I'm explaining myself well. There's already a server side Thread for each client, given the nature of the RMI factory.

    Ah, thanks for the explanation. But you don't have any guarantee that a given RMI implementation will work this way. If I understand correctly that you are making use of the way the RMI mechanism happens to manage Threads under the hood, you are writing non-portable code. Hmmmm.

    I think we're talking about different things here. The solution you're proposing, while it would clean up remote objects, wouldn't have anything to do with releasing the locks held by those objects.

    We are talking about the very same thing. The remote objects are cleaned up anyway; that's not where Unreferenced comes in. The Unreferenced callback represents an ideal opportunity to release all locks held by the (dead) client when the RMI DGC decides that the lease has expired and all remote references have gone.
    - Peter
    [ November 21, 2002: Message edited by: Peter den Haan ]
     
    Ranch Hand
    Posts: 94
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Peter,
    What about using a UID as transaction id for each booking, also use it for locking, and also return it as confirmation number. This UID is generated in the server.
    Charles.
     
    Max Habibi
    town drunk
    ( and author)
    Posts: 4118
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Peter,
    I think I'm starting to see why you're missing my point. The link you reference is in terms of a single remote object: it refers to RMI's discretion in provide a single or multiple threads to each client of that remote object.
    However, that's not at all relevant to what I'm talking about, because I'm not taking about method invocations on a shared object: I'm talking about completely seperate remote objects, one per client: there is no sharing at all. Please re review the factory link I provided.
    In the RMI factory implementation, you create a separate object for each client. Now, if multiple clients were accessing that remote object, then your link above might be relevant. However, since it's only a single client per remote object, it's a complete non sequliar.
    RMI will always create at least a single thread per remote object: it may, or may not, create more threads, if more them a single client tries accessing that remote object.In this case, that's a moot point, because each client gets a separate remote object, and each remote object will have it's own thread.


    We are talking about the very same thing. The remote objects are cleaned up anyway; that's not where Unreferenced comes in. The Unreferenced callback represents an ideal opportunity to release all locks held by the (dead) client when the RMI DGC decides that the lease has expired and all remote references have gone.


    To me, that seems like an excessively clumsy and roundabout way(in this case) that to archive a goal that be more elegantly achieved by using pre existing data structure: namely, the WeakHashMap. Also, remember that the RMI mechanism itself holds a reference to remote objects, the remote object doesn't become available until RMI itself releases it, sometime after the client does so.
    You shrink that interval, of course, by using
    or something along those lines, but that's also just more complexity that, once you dig into it, doesn't buy you much.
    In short, after you add the complexity of un referenced and the corresponding callback, you're still just choosing between the distributed garbage collector and the garbage collector. Pick your own posion, but I tend to prefer the simpler one.
    Part of the criteria of the modern SCJD is not to over engineer a solution, when a more simple one is available. I tend to like simplicity. Apparently, so do the assessors, as the student who implemented this solution got 155/155, with very generous comments.
    HTH,
    M, author
    The Sun Certified Java Developer Exam with J2SE 1.4
     
    Peter den Haan
    author
    Posts: 3252
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by Max Habibi:
    I think I'm starting to see why you're missing my point. The link you reference is in terms of a single remote object [...] RMI will always create at least a single thread per remote object

    Max, don't worry, I'm not missing your point. And this is not at all how I read the RMI specification. It says:

    The RMI runtime makes no guarantees with respect to mapping remote object invocations to threads.

    This is a blanket statement with no further qualification. The context, as I read it, does not imply such a qualification either. But even if you are convinced that each remote object must get its own thread, the quote clearly leaves the possibility that an object may get multiple threads and says with so many words that you have no guarantee which thread is used for a given invocation.
    My understanding of the specification is however that you don't have even that -- that you simply get no guarantees whatsoever about the number of threads, the identity of the threads, and how threads releate to clients, objects and method calls. In older versions of Java, you could perhaps argue that some kind of relation between objects and threads was implied by the RMI wire protocol, but with JDK 1.4 and the java.nio.* packages, even this is no longer the case.
    If you can show me where the specification mandates this both the mapping between objects and threads, and a guarantee that an object will get no more than one thread, I'm more than happy to eat my words

    To me, [Unreferenced] seems like an excessively clumsy and roundabout way(in this case) that to archive a goal that be more elegantly achieved by using pre existing data structure: namely, the WeakHashMap.

    Are you telling me that implementing a simple interface with one method, and one line of code within that method, is more clumsy and roundabout than introducing a whole new data structure that many developers are not terribly familar with, relying on a thread allocation scheme that might be implementation-dependent? Surely you jest.

    Also, remember that the RMI mechanism itself holds a reference to remote objects, the remote object doesn't become available until RMI itself releases it, sometime after the client does so.

    Obviously. How is this different from your solution? After all, the server Thread used by RMI doesn't become available for garbage collection until the DGC finds that the lease for that object has expired. The difference is that in my solution, the locks get cleaned up straightaway once the DGC finds that the object has become unreachable, while in your solution you have an additional wait for an unpredictable garbage collector.
    By the way, if you would ever deploy your solution on an RMI implementation that uses a thread pool, it seems to me that the cleanup code will get more than a little bit confused.

    Part of the criteria of the modern SCJD is not to over engineer a solution, when a more simple one is available. I tend to like simplicity.

    So do I. So if you are creating an object for every client anyway, why for heaven's sake do you insist on using some obscure or even undefined thread management features of RMI to establish a client identity that the object itself can simply provide you? Why do you promote the use of a WeakHashMap to detect the actions of the local garbage collector on Threads that may not be garbage collected at all, where RMI has a well-defined, standard mechanism to warn you about the unreachability of remote objects?

    Apparently, so do the assessors [like simplicity], as the student who implemented this solution got 155/155, with very generous comments.

    Which might just show that the assessors are not omniscient. I scored 152, with full marks for general considerations and the server. I'd never used Swing before and unsurpringly lost some points there. And my conversion utility was crap
    - Peter
     
    Max Habibi
    town drunk
    ( and author)
    Posts: 4118
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Peter, I believe that you are still missing the point. Specifically, the spec says


    The RMI runtime makes no guarantees with respect to mapping remote object invocations to threads.


    Emphasis added.
    You're reading that as


    remote object to threads.


    and swapping out the word 'instantiation' for the actual text, which says 'invocations'. Hence, the misunderstanding. I read the spec to mean invocations of an existing object.
    Basically, IMO, the spec says that multiple clients of the exact same object are not guaranteed to have separate threads. This is consistent with everything I have experienced and said, and a moot point in this discussion, as is your original(incorrect) assertion that a reference to a Thread as a key for a Map is somehow particularly resource intensive.


    If you can show me where the specification mandates this both the mapping between objects and threads, and a guarantee that an object will get no more than one thread, I'm more than happy to eat my words


    I'm not interesting in embarrassing you, or making you eat your words, or any of that sort of nonsense: frankly, I don�t think that�s a constructive attitude. If you're correct, I'm happy to learn from you. If not, then I'm happy to have a discussion about the topic, and add whatever value I can.
    That being said, I never stated the above. I simple asserted that a given remote object would have at least one thread. In turn, if that remote object only has a single client, then there can only exist a single thread per client. This is entirely consistent with the specification.


    Are you telling me that implementing a simple interface with one method, and one line of code within that method, is more clumsy and roundabout than introducing a whole new data structure that many developers are not terribly familiar with, relying on a thread allocation scheme that might be implementation-dependent? Surely you jest.


    I may joust peter, but I never jest . Again, I am saying nothing on the kind. I am simply suggesting a weakHashMap instead of a map. After that, everything takes care of itself. Is that more simply then using callback? Yes, in my opinion. YMMV.


    The difference is that in my solution, the locks get cleaned up straightaway once the DGC finds that the object has become unreachable, while in your solution you have an additional wait for an unpredictable garbage collector.


    The difference is, in your solution, the programmer has to write all this code. In the solution my student took, he takes advantage of java's build in mechanisms, and he doesn't duplicate them.


    Which might just show that the assessors are not omniscient.


    Or it might show that they understand this material better then most.


    I scored 152


    That's a great score, you should be very proud.
    All best,
    M, author
    The Sun Certified Java Developer Exam with J2SE 1.4
     
    Peter den Haan
    author
    Posts: 3252
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by Max Habibi:
    Peter, I believe that you are still missing the point.

    Max, I know I'm not.

    [...] as is your original(incorrect) assertion that a reference to a Thread as a key for a Map is somehow particularly resource intensive.

    Please, I never said this! At the time, I was not entirely clear on what you were proposing -- I got the impression you were creating a Thread in addition to what RMI creates. That, obviously, would have been fairly heavyweight. I'm not bothered about the Map.

    [...] I simple asserted that a given remote object would have at least one thread. In turn, if that remote object only has a single client, then there can only exist a single thread per client. This is entirely consistent with the specification.

    Exactly. This is the crux, and my apologies for not making it clear. No, it is not inconsistent with the specification; of course not. It is the way it currently works. But this behaviour is an implementation detail, not mandated by the specification. In fact the specification as I read it explicitly warns you against making any assumptions of this kind. Today, using java.nio.* and thread pooling techniques, I could write an RMI implementation which is 100% compliant with the spec yet breaks every single one of your assumptions. It might perform significantly better than the current implementation in systems with large numbers of remote objects or with high object churn. Tomorrow, Sun might decide to do go this route for JDK 1.5.
    As I stated earlier, my assessment is that your solution is non-portable. And unnecessarily so. If you disagree, then please quote where the RMI specification guarantees that you get a single Thread per remote object, and no more than a single Thread if you have but one client thread. Because for your architecture to be portable, the threading behaviour you rely on must be mandated by the RMI specification. Arguing that the section I quoted does not apply to you (although we still disagree there) is not enough.

    I am simply suggesting a weakHashMap instead of a map. After that, everything takes care of itself. Is that more simply then using callback? Yes, in my opinion. YMMV.

    The RMI API has a standard, simple mechanism specifically created to allow you to clean up after an object has become unreferenced, as soon as the DGC finds that that is the case. Given that fact, would you go with something else of your own invention that depends critically on current RMI implementation details and has to wait for the garbage collector to do its work? My mileage does indeed vary, considerably so.

    The difference is, in your solution, the programmer has to write all this code. In the solution my student took, he takes advantage of java's build in mechanisms, and he doesn't duplicate them.

    Perhaps I should cut and paste "all this code", so we all know what we're talking about:I don't think three lines of code are too high a price to pay for portability and predictability.
    - Peter
    [ November 23, 2002: Message edited by: Peter den Haan ]
     
    HiBob Chu
    Ranch Hand
    Posts: 86
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Hi Peter:
    Thanks for your advice.
    quote
    ****************************************
    However, there is an additional requirement hidden in the javadoc for unlock() (at least that's where it was in my assignment) that in most implementations requires a client ID of some sort.
    ****************************************
    My assignment has the same instruction about
    unlock. I think my solution meets it too.
    quote
    *****************************************
    There's a problem with this. This presumably means that your server code is tied to the Fly By Night application, which significantly reduces its reusability. And reusability is one of your design goals.
    *****************************************
    In my assignment instruction:
    ************************************************
    You must create a data server that will accept multiple concurrent network connections and allow them to interrogate and manipulate the database. Because multiple concurrent connections may exist, you must make both your server and the suncertify.db classes threadsafe. You may implement your threaded server in more than one class if you choose.
    *************************************************
    I have a server class which is a remote object and hand all connections with clients.
    And another class object is in charge of business
    logic for example BOOK.
    So it is not only reuseable but also easy to extends to three tier model.
    So , I believe that the solution without clientID is one of the right solutions
    Regards.
     
    Max Habibi
    town drunk
    ( and author)
    Posts: 4118
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by Peter den Haan:
    --------------------------------------------------------------------------------
    Originally posted by Max Habibi:
    Peter, I believe that you are still missing the point.
    --------------------------------------------------------------------------------
    Max, I know I'm not.


    Peter, we'll just have to agree to disagree on this. Eventually, experience will make one of us wiser. Hopefully, it will be me.


    As I stated earlier, my assessment is that your solution is non-portable.


    First, it is not my solution, but the solution of one of my more talented students. Second, your assessment is incorrect. Why? Because there are only two possibilities here. One is that a separate Thread is created per each unique remote object, in which you agree(I think) that the scheme works. The second is a sinlge thread is created for all remote objects. In which case, if you think it through, the scheme also works. The dichotomy you�re seeing is a false one.

    The RMI API has a standard, simple mechanism specifically created to allow you to clean up after an object has become unreferenced, as soon as the DGC finds that that is the case. Given that fact, would you go with something else of your own invention that depends critically on current RMI implementation details and has to wait for the garbage collector to do its work?


    This reminds me of a client, who shall remain nameless, who was using RMI to communicate between separate windows of the same client side application. When I asked why, the lead architect said the fact that RMI could be used that way justified the decision. I told him that, just because I would pick up my sandwich, take a walk around the block, then take a bite, didn't mean that I should do so.
    Peter, my student did not invent the weakHashMap: Sun did. He�s just understands the material well, and it using it properly. Now, should I encourage a heavy handed and overly complex way to solve the problem, or a more simple approach? I prefer the simple way. Again, YMMV, but the total distance remains constant.


    don't think three lines of code are too high a price to pay for portability and predictability.


    It�s not just three lines of code Peter, because there are other parts of the application that are supporting it. However, IMO, a single line of wasted code is too much. Why wasted? Because it doesn't by you anything that the simpler approach doesn't have, other then useless complexity.
    M, author
    The Sun Certified Java Developer Exam with J2SE 1.4
    [ November 25, 2002: Message edited by: Max Habibi ]
     
    ranger
    Posts: 17347
    11
    Mac IntelliJ IDE Spring
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Ding, Ding, Ding, The bell rings ending round 12.
    I cannot render a decision on who is correct here, in one easy statement.
    I take the RMI Specification meaning that when it comes to threads there are no guarantees anywhere.
    But I could be wrong.
    Now a Junior Programmer will definitely not know that answer.
    So then by providing the Connection object instead of using some lesser known SUN made classes, tends to make it easier for a junior programmer to catch on.
    And that is one of the requirements of the assignment.
    Unreferenced I found to be the easiest interface around next to Serializable.
    I have never seen anyone lose points for the Connection and Unreferenced solution. However, I have not seen many people us the Thread way, so can't comment on their scores.
    I do know that with all cases of people here, the Connection solution was the easiest to understand and people got it. Which leans me towards the Connection solution being easier for junior programmers to understand.

    Now on Max's side, if the Thread in RMI in independent Remote Objects on the server side handles the same uniqueness as the Connection class without using Unreferenced then it is using the objects already available for the solution, therefore saving a level of abstraction in the solution. and it decreases the amount of code needed to be written.
    Now Max I have a question about the above statement. Let's say there is a client crash and that client has a lock on record #2, how does your solution unlock record #2 for the client after it has crashed?
    I know Max to be very knowledgable about all of Java's api's, so I can't say that he is wrong in any of his statements.
    Good Luck guys.
    Ding Ding, round 13 is just starting.
    I think this is a case where neither side wants to budge and probably won't regardless of whether one solution is more right than another. So I would suggest that all the points are on the table and anymore posting will just be repeating the same stuff, but won't get us a resolution.
    No I hope I was a politcally correct as I possibly can get and still have both of you here to help us all out.
    Mark
     
    Peter den Haan
    author
    Posts: 3252
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    1:N and N:N mappings are by no means your only implementation choices; in fact, most threading systems that need the last word in scalability tend to use M:N type mappings. And the actual invocation threads could potentially come at random from a thread pool. Also it escapes me for the moment how the architecture will perform with just one Thread, if your entire concept of client identity depends on it. But far more importantly, the question where the RMI spec mandates the threading behaviour you require still stands.
    That Sun provided the WeakHashMap is beside the point. In my part of the world, if a well-documented, public API exists to accomplish a certain task, doing your own thing to do the same is frowned upon. If that own thing depends on implementation assumptions which may be broken anytime it is considered bad engineering.
    There is no code to support the unreferenced() method, it's three lines only. All else I needed anyway to implement close().
    But in one thing you're absolutely right, we'll have to agree to disagree. Let the reader of this thread make up his/her own mind.
    We probably chased everyone else away by now anyway
    - Peter
    [ November 25, 2002: Message edited by: Peter den Haan ]
     
    Max Habibi
    town drunk
    ( and author)
    Posts: 4118
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Now Max I have a question about the above statement. Let's say there is a client crash and that client has a lock on record #2, how does your solution unlock record #2 for the client after it has crashed?
    Mark


    Hi Mark,
    I tend to like this sort of discussion, so long as it remains cordial: it's enriching for both parties. However, I think I'm pretty much done with this topic: Peter has his interpretation of the specs, and I have mine. As I said, experience will, at some point, change one of those opinions.
    Now, to your question.
    Because the thread is the key in a weakHashMap, once the remote client dies, RMI will eventually release it's reference to the Thread. There will be no references to the Thread, so it will be released. Thus, the value in the map, in this case, the lock, is released.

    All best,
    M, author
    The Sun Certified Java Developer Exam with J2SE 1.4
     
    Peter den Haan
    author
    Posts: 3252
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by Mark Spritzler:
    [...] I have a question about the above statement. Let's say there is a client crash and that client has a lock on record #2, how does your solution unlock record #2 for the client after it has crashed?

    The Thread representing the client identity is the key to the WeakHashMap, and presumably the lock(s) held by the client are the corresponding value. When the Thread is garbage collected, the WeakHashMap automatically drops the lock(s). Max, is this right? You must admit, the idea is very neat.
    Obviously, this mechanism critically relies on the Threads being garbage collected at all. So if your RMI implementation uses a thread pool, it breaks. I don't think anyone is arguing that the RMI specification precludes the use of a thread pool, which makes this method non-portable. You can get around this problem by making the Remote object itself the key -- but then, of course, you just end up with the Connection architecture we both know and love.
    The Thread in question belongs to the ServerRef created when the Remote object is exported (if you subclass UnicastRemoteObject, it is exported automatically). When the RMI distributed garbage collector (DGC) finds that no-one has a remote reference to your object anymore, it invokes unreferenced() (if the object implements Unreferenced) and drops its references to the ServerRef and the object. Some unpredictable time after that, everything including the Thread gets garbage collected. Note "unpredictable". Note "after that", i.e. after calling Unreferenced. And of course, the Thread just may not.
    Finally, the Thread must be the key in the WeakHashMap, because the values are held using strong references. To me, this seems to be exactly the wrong way around. This makes finding all the locks held by a given client an O(1) operation, and finding whether a given record is locked an O(N) operation. I would expect to do the latter far more often than the former.
    - Peter
    [ November 25, 2002: Message edited by: Peter den Haan ]
     
    Max Habibi
    town drunk
    ( and author)
    Posts: 4118
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Peter, it's a small world. I happen to know one of your co authors on your networking book.

    Originally posted by Peter den Haan:
    1:N and N:N mappings are by no means your only implementation choices


    Of course not, but that�s not Germaine. Even if RMI were implemented that way, which it�s not to the best of my knowledge, better Thread pool implementations still give each Thread a set of clients for which it is responsible.


    That Sun provided the WeakHashMap is beside the point.


    Not at all, it is precisely the point. Sun provides a simple solution: why choose the roundabout way? Even if you want to use the Client object and not the Thread, you still don�t need unreferenced: it�s just fat.


    In my part of the world, if a well-documented, published API exists to accomplish a certain task, doing your own thing to do the same is frowned upon.


    It's the same way here in the States. However, in my neck of the woods, if a simple java.util.*(which is also well-documented and published) class can solve a problem, then you don't need to dig into networking and increase your complexity. IMO, that's fairly bad engineering.


    But in one thing you're absolutely right, we'll have to agree to disagree. Let the reader of this thread make up his/her own mind.


    Indeed.


    We probably chased everyone else away by now anyway


    Indeed, it�s starting to chase me away too. Let�s just agree to buy each other a beer and discuss it till dawn if we ever meet at a conference or some such. As for this discussion, you can have the last word after this post.
    All best,
    M, author
    The Sun Certified Java Developer Exam with J2SE 1.4
     
    Ranch Hand
    Posts: 67
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Max & Peter,
    Frankly saying, just to see both of your posts I see this thread couple of times every hour
    So you are not chasing away anyone I believe rather attracting people like me.
    I by myself learned a lot from your discussion. You may stop on this topic here but please don't hesitate to start discussion on any other topic here.
    Regarding the subject I personally bending towards Peter's solution.( that is my sense judzment after reading the whole thread several times.) Since you both already defeated to convince other, I don't want to try to convince or support any one.
    Many thanks for both of you for having such a nice discussion in this forum.
     
    Peter den Haan
    author
    Posts: 3252
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Max, I don't care for that last word, but would like to add that I tremendously enjoyed the discussion. Happy also to know that our jests, jousts, thrusts and parries helped some ranchers gain a deeper understanding.
    That beer sounds great I'll buy the first, virtual round
    - Peter
     
    Villains always have antidotes. They're funny that way. Here's an antidote disguised as a tiny ad:
    a bit of art, as a gift, the permaculture playing cards
    https://gardener-gift.com
    reply
      Bookmark Topic Watch Topic
    • New Topic