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 R
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.
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.
You are correct. The text is wrong. RMI stubs are thread-safe and can be invoked simultaneously by multiple threads within a single client JVM. I'm not aware of any statement or text by Wollrath et all that says anything different, and I've been following this topic since 1997.
Specifically:
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).
You are correct.
In the book it's instead said that concurrent execution of synchronized methods is not prevented when using RMI.
The book is not only wrong, it is stating an impossibility. How exactly could RMI prevent synchronization from working?
Logically, blocking in a remote object is simple. Suppose that client A calls a synchronized method of a remote object.
Then blocking occurs at the server, by the normal operation of Java.
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.
Rubbish. The fact that the remote method implementation is synchronized
does everything that is necessary.
Likewise, another client on a different machine would need to be blocked locally as well before its request can be sent to the server.
Again this is rubbish.
The consequence is that we need to synchronize different clients at different machines.
Rubbish again.
An alternative approach would be to allow blocking only at the server.
'Allow'? What does this mean? A synchronized
method is synchronized.
You can't disallow it.
In principle, this works fine, but problems arise when a client crashes while its invocation is being handled by the server.
Again rubbish. No such problems arise. The server recovers from this situation either via a read timeout or an write exception or even successful completion of the remote method. In all three cases, the method exits, the synchronization lock is released, and life continues.
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.
Nonsense.
Therefore, the designers of Java RMI have chosen to restrict blocking on remote objects only to the proxies (Wollrath et al., 1996).
I am not aware what else this could refer to other than the excerpt you quoted, and I've read that paper many times. If the authors want to rely on this paper they should have provided a quotation and a proper citation to chapter and verse.
In any case the designers of RMI made no such choice. There was no such choice to make. synchronized
is synchronized
whatever the RMI designers may or may not have wished, and similarly notify()
and wait()
are final.
They weren't free to make any choice. The quotation you provided isn't a 'choice': it is merely a statement about the semantics of Java.
Am I interpreting the text in the wrong way or is in fact stated that synchronized methods are "not so synchronized" when using RMI?
I think you're reading it correctly, and it's completely and utterly wrong, and not only wrong but obviously wrong. How could it possibly be right?
Java RMI doesn't, and indeed cannot, alter or remove or extend the semantics of synchronized
in any way.
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.