Fly by Night Consultants<br /> <blockquote><font size="1" face="Verdana, Arial">quote:</font><hr><i>I climbed on the back of a giant albatross<br />which flew through a crack in the cloud<br />to a place where happiness reigned...<br />all year 'round<br />the music played ever so loudly!</i><p><a href="http://thomasfly.com/songs/Traffic/Hole_in_my_Shoe_qt.htm" target="_blank" rel="nofollow">Hole in My Shoe</a><hr></blockquote>
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.Originally posted by Max Habibi:
You can lock a client based on Thread id(or Thread), if each client has their own Thread.
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
Originally posted by Peter den Haan:
Yikes. I hope you meant to say "Object" where you said "Thread".
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.Originally posted by Max Habibi:
No, I meant Thread: Remember, the only thing that gets stored in a map is a reference
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.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.
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
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.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.
Although it is a Good Thing to handle this situation, I'm not sure you will be penalised if you don't.In this way, How to deal with the exception of client dying?
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.I putted the book action into a server end class.
You can change the signature, if you have a very good reason to. Of course you should clearly document this design decision.And another reason why shouldn't keep clientID is that the signature of lock , unlock shouldn't be change.
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
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
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.
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.
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.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.
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.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.
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
Charles.<br />(SCJD2)
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.
Max, don't worry, I'm not missing your point. And this is not at all how I read the RMI specification. It says: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
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.The RMI runtime makes no guarantees with respect to mapping remote object invocations to threads.
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.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.
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.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.
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?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.
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 crapApparently, so do the assessors [like simplicity], as the student who implemented this solution got 155/155, with very generous comments.
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
The RMI runtime makes no guarantees with respect to mapping remote object invocations to threads.
remote object to threads.
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
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.
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.
Which might just show that the assessors are not omniscient.
I scored 152
Max, I know I'm not.Originally posted by Max Habibi:
Peter, I believe that you are still missing the point.
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.[...] as is your original(incorrect) assertion that a reference to a Thread as a key for a Map is somehow particularly resource intensive.
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.[...] 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.
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.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.
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.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.
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
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.
As I stated earlier, my assessment is that your solution is non-portable.
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?
don't think three lines of code are too high a price to pay for portability and predictability.
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
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
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.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?
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
Originally posted by Peter den Haan:
1:N and N:N mappings are by no means your only implementation choices
That Sun provided the WeakHashMap is beside the point.
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.
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
<B>Prasad</B>
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd