Hi, Now, I am a little confused about RMI and the locking mechanism. My design has multiple data (export to clients), one singleton LockManager which uses wait() and notifyAll(). Most of time, the program runs well in RMI and local modes. However, there are one case in which one record can be locked twice in the network scheme. I think this may be due to the fact that RMI only create one thread for multiplex clients, thus this thread can always hold Lockmanger's Monitor and call codes in synchronized mode.
I have no idea how to make sure one thread for each client. This may not be possible? Any possible solution for this one? Really appreciate your help. Regards. Rick
Rick, if you do a search on this forum on "Connection" you will find a solution that creates an Object for each client, that will reside on the server side. This creates a one to one relation. Each of these Connection objects holds a reference to the LockManager, so only one client at a time can hold the lock on the LockManager. Mark
Hi Mark, Thanks for your reply. I think I did't explain it clearly. Actually I used the connection factory to export a new Data Class for each client. But RMI specification said:
A method dispatched by the RMI runtime to a remote object implementation may or may not execute in a separate thread. The RMI runtime makes no guarantees with respect to mapping remote object invocations to threads.
So even multiple Data objects are created, no guarantees that each Data object will executed with one thread. in which case, wait() can be called by the same thread twice or more because wait() and notifyAll() are based on "THREADS" instead of "OBJECTS", right?( When the thread is in wait(), it can execute some other methods, is it ture???) This can cause unexpected system behaviors. I have wrong understanding on threads??? Or, any suggestion??? Rick
"to export a new Data Class for each client" This tells me that you are not using the Connection factory solution, that you will find in this forum. In that solution there is only one Data class, whose reference is passed to each client's Remote Connection object residing on the server. If you export a new Data class for each client, then there are more than one instance of the Data class, and therefore 0 percent chance of thread safety. Mark
In Max's book, he only had one Data instance for all clients. But in my current implementation, I create a new Data instance for each client. However, LockManager is a static (singleton) member in the Data class. Following is my connection factory, there are two classes that extends UnicastRemoteObject: DataRemoteImpl and ConnectionFactoryImpl. The reason I create multiple Data instance is that there are too much computation workloads in it. So multiple instances can be more efficient.
DBClient is the interface that looks like DBMain but with one extra method "getMetaData(). Is this the right way to implement Connection Factory? Rick
I think this may be due to the fact that RMI only create one thread for multiplex clients
No. The number of threads that RMI creates is unknown. And which thread will be used to process any given method is undetermined. You have to use the Sun JDK for this assignment, and so far my testing on Solaris, Linux, Windows 2000, and Windows 95 all shows that multiple threads are used. I would be extremely surprised if Sun released an RMI implementation that only used one thread. However it is technically possible according to the specifications, and any other manufacturer's RMI implementation can do whatever they wish.
However, there are one case in which one record can be locked twice in the network scheme.
I doubt that this would be due to which thread you are using to lock the record. I am more likely to believe that there is some other problem.
I have no idea how to make sure one thread for each client. This may not be possible?
The RMI Specification is explicit that you have no control over which threads are used by RMI. But as mentioned before, I don't think that this is really your problem.
So even multiple Data objects are created, no guarantees that each Data object will executed with one thread. in which case, wait() can be called by the same thread twice or more because wait() and notifyAll() are based on "THREADS" instead of "OBJECTS", right?( When the thread is in wait(), it can execute some other methods, is it ture???) This can cause unexpected system behaviors.
No - when you call wait() it forces the specified thread to wait. That thread should not be used for any other instances.
Is [the code posted] the right way to implement Connection Factory?
Yes, that will get you a connection factory. Some general questions about your code: Why do you call super() in your constructors to DataRemoteImpl() and ConnectionFactoryImpl()? Why do you have a create() method in DataRemoteImpl? Surely it should only be used by the constructor, in which case why not move the logic into the constructor? Why have you hard coded "localhost" into your hostService string? Regards, Andrew
Hi Rick, You can use localhost. Since you are starting the RMI Registry yourself, that is a nice safe option for the server. The Sun RMI Registry will not allow you to run your service on a machine other than the one where the RMI Registry itself is running. But the specification allows for the two to be on different machines. So in a commercial environment, you might want to have something other than localhost. Likewise the Sun RMI Registry seems to accept any call on any TCP/IP interface associated with the local host, regardless of what IP address you put in your bind call. But many other servers will only listen on the named IP address. So I would not be surprised if some other registry actually honoured the "localhost" and refused to accept calls from other machines even on the same subnet. All of which is beyond the requirements. What I meant to ask was whether you used "localhost" on the client side, or whether you allowed the user to specify the IP address. Regards, Andrew