views:

188

answers:

4

(Please leave a comment if the point is not clear)

I'm studying the book "Distributed Systems" (by Tanenbaum & Van Steen) and they say something that seems to conflict to what seems to be instead thought by many on Java RMI and synchronized methods.

What I thought is that using a synchronized method on a Remote Object implementation (so the real implementation running at the server) concurrent execution of that method is prevented even when the calls to that method are from different clients machines (calling the method via a Proxy... aka a Stub).

I've seen that a lot of people have the same opinion, look here for example: http://stackoverflow.com/questions/2275868/java-rmi-and-thread-synchronization-questions

In the book it's instead said that concurrent execution of synchronized methods is not prevented when using RMI.

Here's the relevant excerpt from the book (you can read the bold sentence only, but you can read the context if you prefer to):

Logically, blocking in a remote object is simple. Suppose that client A calls a synchronized method of a remote object. To make access to remote objects look always exactly the same as to local objects, it would be necessary to block A in the client-side stub that implements the object's interface and to which A has direct access. Likewise, another client on a different machine would need to be blocked locally as well before its request can be sent to the server. The consequence is that we need to synchronize different clients at different machines. As we discussed in Chap. 6, distributed synchronization can be fairly complex.

An alternative approach would be to allow blocking only at the server. In principle, this works fine, but problems arise when a client crashes while its invocation is being handled by the server. As we discussed in Chap. 8, we may require relatively sophisticated protocols to handle this situation, and which that may significantly affect the overall performance of remote method invocations.

Therefore, the designers of Java RMI have chosen to restrict blocking on remote objects only to the proxies (Wollrath et al., 1996). This means that threads in the same process will be prevented from concurrently accessing the same remote object, but threads in different processes will not. Obviously, these synchronization semantics are tricky: at the syntactic level (ie, when reading source code) we may see a nice, clean design. Only when the distributed application is actually executed, unanticipated behavior may be observed that should have been dealt with at design time. [...]

I think that the paper "A Distributed Object Model for the Java System" (available here) is referenced in the text by the note Wollrath et all, 1996 between parenthesis. However the only relevant paragraph I've found on that paper is this one:

Due to the differing failure modes of local and remote objects, distributed wait and notification requires a more sophisticated protocol between the entities involved (so that, for example, a client crash does not cause a remote object to be locked forever), and as such, cannot be easily fitted into the local threading model in Java. Hence, a client can use notify and wait methods on a remote reference, but that client must be aware that such actions will not involve the actual remote object, only the local proxy (stub) for the remote object.

Am I interpreting the text in the wrong way or is in fact stated that synchronized methods are "not so synchronized" when using RMI?

+1  A: 

As far as I know each call to an RMI server will create a new thread (witnessed by my log files from 2000) on server side. If you do synchronizing at server side you should be safe. I faced some ancient warnings from literature as you posted. As an practicioner I prefered to run the software for a month or so and decided it was stable enough for for production. I'm Sorry if this isn't not satisfying.

stacker
+2  A: 

You should also be aware that Java multi-threading has changed significantly since 1996. The notify() and wait() methods that were part of the original language design got a lot of flack from concurrency experts and in Java 5 (2004, says wiki) high level concurrency objects like the ReentrantLock were introduced which are now the preferred way of doing things.

So the criticisms you mention are probably correct, but outdated.

Michael Clerx
Good point. I overlooked the date on that.
DrDipshit
A: 

I think main difficulty may lay in scenario like that:

  1. Create object at caller:

    final Object lock = new Object();

  2. In client, pass it via RMI call to remote server:

    remote.doSomeStuff(lock);

  3. In server, try to do sync:

    void doSomeStuff(final Object lock) { synchronized(lock) { ... } }

  4. Now, main problem is how to ensure synchronization between server & client, in case when client also wishes to acquire monitor of lock object.

Victor Sorokin
Well, in that situation i think it's a pretty common opinion that the synchronization is in fact on the lock stub, not the remote object. So, in general, that when you write `synchronized(object){...}` and if object is a remote object, you are in fact synchronizing on the local stub and not on the remote object. I would not expect something different.But note that the problem that the question speaks about is totally different. Your answer poses the problem of distributed synchronization, while my question is on local synchronization (where synchronizations are in the server side).
Andrea Zilio
I think that problem vaguely mentioned in `Wollrath` excerpt relates to scenario I described.I would expect server-local sync to work, since would it not work it will mean violation of Java concurrency framework. And it would be very strange :)
Victor Sorokin
A: 

What your first reference is saying is that within a single VM instance, invocations on an RMI Stub (client to an RMI server) will be internally synchronized. That is, the stub (or proxy, as the text seems to call it) itself will prevent multiple threads from concurrently invoking a method on the remote server. It clarifies, however, that two VMs each with stubs for a remote server will not be blocked from concurrently invoking the remote server (which is obvious, because they cannot share a lock, and RMI itself does not prevent concurrency at the server). If this is undesirable, the RMI server will have to implement a locking mechanism to prevent multiple concurrent invocations.

The second reference does not in anyway contradict the first. The second merely clarifies that if you try to synchronize on a stub, it will only be locked locally, and will not impact the concurrency of the remote server.

Combining the two texts, we can read that synchronizing on a stub will prevent the multiple threads in the same VM from concurrently accessing the remote, but will not prevent threads in distinct VMs from concurrent access.

mwhidden