Threading and RMI Threads

} The following three-way transaction can cause deadlock: • Bob tries to pay his electric bill by transferring money into the utility companys account. • The utility company is transferring money to Bobs employer, to pay a past-due bill. • Bobs employer is directly depositing Bobs paycheck again, transferring money. How do we get around this particular problem? Its hard, and well beyond the scope of this book. The best way to do so is to use a distributed-transaction manager. Programming with Enterprise JavaBeans, JTS, and OTS by Andreas Vogel and Madhavan Rangarao John Wiley Sons is a good place to start learning about distributed-tranaction management. Well also briefly revisit transaction management in Chapt er 17 .

11.6 Threading and RMI

Given that I opened this chapter by talking about the need for multithreaded servers, and given that weve spent 30 pages or so on the basic thread manipulation operations in Java, you might think that the RMI specification goes heavy on the details of the threading model. Youd be wrong. Heres all of what the RMI specification says about threading: 3.2 Thread Usage in Remote Method Invocations 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. Since remote method invocations on the same remote object may execute concurrently, a remote object implementation needs to make sure its implementation is threadsafe. In practice, threading in RMI is fairly simple. On the client side, RMI adds no threading complications. Remote method invocations on the client side consist, more or less, of code that behaves exactly like our socket code. That is, a request is marshalled and sent through a socket. The thread sending the request then tries to read a response back from the server, over the socket. This means that the calling thread on the client blocks until the server sends a response. This model of remote method invocation is nice because it corresponds to what happens with local method invocation. That is, we have: Local method invocation A new frame is put on the stack, corresponding to the new method call. Processing in the previous method call stops the thread is executing the new stack frame. Eventually, a value is returned, and processing resumes in the original stack frame. Remote method invocation A new frame isnt put on the stack. Instead, processing blocks at the socket level, waiting for the return value. Meanwhile, on the server, a different thread attempts to handle the request and return a value. As part of this, a request-handling thread executes a local method invocation. In essence, the RMI messaging model simply puts part of the stack on the server side. This is often referred to as a synchronous messaging model. Meanwhile, on the server, things are more complicated. The following sequence of operations occurs in every RMI server whenever a request is made: 1. When a remote request comes in, it is immediately demarshalled into a request object that encapsulates the method invocation. This request object, which is an instance of a class implementing the RemoteCall interface, has a reference to the sockets output stream. This means that, although RMI shares sockets, a socket is used only for one remote method invocation at a time. 2. The thread that received the request from the socket finds the intended remote object for the method invocation, finds the skeleton associated with that remote object, and invokes that skeletons dispatch method. The dispatch method has the following signature: 3. public void dispatchjava.rmi.Remote obj, java.rmi.server.RemoteCall call, int opnum, long hash throws java.lang.Exception 4. The skeletons dispatch method invokes the right method on the server. This is where the code you wrote is actually executed. 5. The server method returns a value, which is eventually propagated back through the socket on which the original request was received. There are two important points to note. The first, and by far the more important, is that your server code must be threadsafe. RMI allows many threads to enter a server object. But, if your server is too heavily synchronized, you will either wind up deadlocked or locking out a lot of the threads for extended periods of time. Hence, you run the risk of timing out a significant percentage of the remote method invocations. The second point concerns socket allocation. RMI shares on sockets. This means that it tries to reuse sockets between the client JVM and the server JVM whenever possible. But when a socket is being used by a remote method invocation, it is not available for reuse. This means that the number of sockets allocated to a client is really equal to the number of simultaneous requests a client is making. Since the number of sockets available to an RMI server is limited, and socket allocation is expensive, this can affect scalability. Congratulations Between the early socket chapters, in which you learned how to send data over the wire; Chapt er 10 , in which you learned how to marshall objects using serialization; and this chapter, in which I covered threading and the details of handling remote method invocations in a server, you now know enough to write an RMI implementation. [ 7] [ 7] I wouldnt recommend it, though. Lifes too short.

Chapter 12. Implementing Threading