wiki:JavaParty/DistributedThreads

Distributed Threads

Since JavaParty 1.07a

When a remote method is called, the actual thread sends the method arguments and blocks until the method result is available. After reception of the result, it continues. On the server side, a thread unrelated to the original one receives the method invocation, executes the requested method and returns the result over the network. From a bird's eye view, the control flow moves during the remote call from one virtual machine to another and returns to the original machine when the method returns. Such control flow that spawns multiple nodes is called a "distributed thread". Since Java threads are bound to their virtual machine they are created in, a remote method execution is mapped to two different Java threads: the client thread that initiated the call, and the server thread that executes the remote method on the remote node. These two threads are both representatives for the same distributed thread of control. Each segment of the distributed thread is mapped to a particular local Java thread for execution.

As long as remote method invocations are not nested, the application is unlikely to observe that a single control flow is mapped to different Java threads. If remote invocations are nested, and each segment of the distributed thread is executed in its own thread, the following situation as shown in figure 1 can occur:

source:trunk/jp/src/doc/image/distributed-threads-recursion1.png
Figure 1. A distributed thread re-entering its original node.

Figure 1 describes a distributed thread that first calls a method of object a and b before invoking its first remote method on object c that lives on another virtual machine VM 2. Object c on his part now also calls a method on object b that lives on the same virtual machine VM 1 where the distributed thread originated.

At this point in time, the described distributed thread consists of three segments. The first segment lies on VM 1 and is executed on behalf of Java thread t1. The second segment is on VM 2 and is executed in Java thread t2. The head segment, where the current point of execution is, lies on the same node VM 1 as the first segment. It is executed in thread t3. Threads t1 and t3 both exit on the same virtual machine and represent different segments of the same distributed thread.

This situation may cause an unexpected dead-lock, if the application entered a synchronization in segment 1 and tried to re-enter the synchronization in segment 3. As one expects form regular non-distributed Java, one thread should be able to enter the same synchronization several times. But here the distributed thread is implemented by two different Java threads. The first Java thread t1 still holds the synchronization acquired in segment 1 when the second thread t3 tries to enter the same synchronization. Since the Java virtual machine on node VM 1 hast no knowledge that these two threads are both representatives for the same distributed thread, thread t3 is blocked waiting until thread t1 leaves the synchronization. But since t1 waits for its remote invocation to return, this will never occur, which produces a dead-lock.

KaRMI provides a solution for the problem described above by tracking the flow of a distributed thread across the borders of a single virtual machine and assigning an unique representative thread to a distributed thread per node. The unique representative is responsible for executing all segments of the distributed thread falling on its node. The above situation is shown again shown in figure 2 using the unique representative approach.

source:trunk/jp/src/doc/image/distributed-threads-recursion2.png
Figure 2. Unique representative for a distributed thread.

In figure 2 thread t1 is the unique representative for the distributed thread shown. When it encounters the first remote invocation to node VM 2 it does not simply wait for the method result to become available, but it also keeps listening for further remote method invocations that may arrive at VM 1 for its distributed thread. If such invocation arrives, it is executed by the representative t1, instead of another server thread being spawned. This situation occurs when the method of object c decides to call back the second method of object b. Now no new thread t3 executes this method, but the unique representative t1.

This unique representative approach provides full synchronization reentrance for a transparent distributed environment. RMI and most other RPC middle-ware systems that rely on remote execution do not care about distributed threads. Using these systems, you will actually experience a dead-lock in the situation described above.

KaRMI in combination with JavaParty can do even more by providing completely Transparent Threads in a distributed environment. Please read more about Remote Monitor Access (RMA), and JavaParty Synchronization in the following sections.

Last modified 10 years ago Last modified on Jan 17, 2007 10:47:42 AM