Readers/Writers on Java RMI


Readme/index.html file

Due to "strange" and unexplained (at least for me) policies/changes  of this server, this page/site is out of date since Jun 2009. The new page/site with this content is

 

 

Copyright (C) 2007 Fernando G. Tinetti (my web page at UNLP)

License
This code is released under the GNU GPL version 2 or any later version.
http://www.gnu.org/copyleft/gpl.html


Different ways for solving the readers/writers problems in the
context of rmi, i.e., having an "access" server implemented with
rmi. This server is used just for controlling the access to the
shared resource (database, filesystem, etc.). Technical details
on rmi are assumed to be known.

The only a priori requirement is that one or more readers could
access concurrently and at most one writer (without any other
concurrent process) may access the resource.

On other words: a reader process must wait if there is a writer
process accessing and a writer process must wait if there is/are
other process/es accessing (one or more readers, or another
writer).

Most of the code for this series is related to that found in
http://beg.projects.cis.ksu.edu/examples/small/readerswriters/
and references therein:
Dr. Mizuno's paper "A Structured Approach for Developing
Concurrent Programs in Java"
Doug Lea's book, Concurrent Programming in Java

All of the versions are defined separately trying to be self
contained

Every reader process should ask for accessing the resource for
reading via
accessReader()
and should warn when ending the read access with
leaveReader()

Analogously, every writer process should make similar
asking/warning through
accessWriter() and leaveWriter()
respectively

In all of the cases, the process is assumed to get the access
when the rmi returns successfully (not on exception)


Files
-----

Readme/index.html: this file

remoteMethod.java: the interface defining the four methods to
be remotely invoked. According to the comments on the file:
* remoteMethod.java
* Interface defined for the class with the remote methods to be
* used from the "client" side and implemented on the "server".
* Thus, only the four methods (access/leave Reader/Writer) are
* defined, all of them throwing RemoteException


startRemoteObject.java: the class having a main() to create
and register one "server" object (this object belongs to the
class which implements the interface with "remote" methods).
According to the comments on the file:
* startRemoteObject.java
* Starts the remote object. More specifically:
* 1) Creates the object which has the remote methods to be
* invoked
* 2) Registers the object so that it becomes avaliable
* The specific object to be created and registered depends on
* the line
* remoteClassv<i> robject = new remoteClassv<i>();
* where <i> is the number (version) of the "server" implemented
* Expects a local rmiregistry running and waiting on the
* default registry port.
* Used with
* java startRemoteObject


askRemote.java: the "client" process, acting as a reader
process or a writer process depending on a command line
parameter. According to the comments on the file:
* askRemote.java
* Expected to be used as a "client", behaving as a reader
* process or a writer process depending upon the "command
* line argument".
* Access the resource by 5 secs. (hardcoded), this is the
* elapsed time between the return from access...() and the
* call to leave...()
* Used with
* java askRemote <hostname> <Read/Write>
* <hostname>: hostname or IP of the host where the remote
* object ("server") is "waiting"
* <Read/Write>: Read ==> reader process
* Write ==> writer process


remoteClassv<i>.java (i = 1, 2, ..., 7): different
implementations of the remoteMethod interface, i.e.
different "server" policies. According to the comments on
each one of them:
remoteClassv1.java
* This is "Version 1 server" i.e.:
* 1) No priorities.
* 2) With a unique "waiting queue" for every process that should wait.
* 3) Added synchronized to each remote method, to avoid race conditions.
* Used from startService, which creates and registers one object of
* this class.
* Note that keyword "synchronized" is added to each remote method and
* this does not violates the specification, since "synchronized" is not
* part of the method's signature.
* Used from startService, which creates and registers one object of
* this class.

remoteClassv2.java
* This is "Version 2 server" i.e.:
* 1) Readers do not enter if there are writers waiting.
* 2) With a unique "waiting queue" for every process that should wait.
* 3) Added synchronized to each remote method, to avoid race conditions.
* Note that keyword "synchronized" is added to each remote method and
* this does not violates the specification, since "synchronized" is not
* part of the method's signature.
* Used from startService, which creates and registers one object of
* this class.

remoteClassv3.java
* This is "Version 3 server" i.e.:
* 1) Readers do not enter if there are writers waiting.
* 2) After a writer, a waiting reader get access (just one) if there is one.
* 3) With a unique "waiting queue" for every process that should wait.
* 4) Added synchronized to each remote method, to avoid race conditions.
* Note that keyword "synchronized" is added to each remote method and
* this does not violates the specification, since "synchronized" is not
* part of the method's signature.
* Used from startService, which creates and registers one object of
* this class.

remoteClassv4.java
* This is "Version 4 server" i.e.:
* 1) Readers do not enter if there are writers waiting.
* 2) After a writer, a waiting reader get access (just one) if there is one.
* 3) The conditions under which readers or writers get access to the
* resource are checked in a separate function.
* 4) Other policies could be defined and checked in the proper function as
* well. Also, it could be needed (for those policies) to define and use
* specific local variables in order to enforce the policy (as variable
* "last" in the current example).
* 5) With a unique "waiting queue" for every process that should wait.
* 6) Added synchronized to each remote method, to avoid race conditions.
* Note that keyword "synchronized" is added to each remote method and
* this does not violates the specification, since "synchronized" is not
* part of the method's signature.
* Used from startService, which creates and registers one object of
* this class.

remoteClassv5.java
* This is "Version 5 server" i.e.:
* 1) Readers do not enter if there are writers waiting.
* 2) After a writer, a waiting reader get access (just one) if there is one.
* 3) The conditions under which readers or writers get access to the
* resource are checked in a separate function.
* 4) Other policies could be defined and checked in the proper function as
* well. Also, it could be needed (for those policies) to define and use
* specific local variables in order to enforce the policy (as variable
* "last" in the current example).
* 5) Each kind of process (i.e. readers or writers) now wait on a separate
* "watiting queue" associated to a specific monitor. An instance of the
* Object class is used directly as a monitor (which in fact it is).
* More specifically, these monitors are used just as waiting and
* synchronizing queues, just to make wait/notify calls on them.
* 6) The remote methods are not "synchronized" now, since two monitors are
* used: one to test and set for access conditions and one to wait
* (well, two in general, one for readers and one for writers). The
* monitor to test and set for access is "this", the access server
* itself.

remoteClassv6.java
* This is "Version 6 server" i.e.:
* A rather different approach (from the previous ones), since
* concurrent readers are allowed for every (reader) request
* previous to a writer request and after a writer leaving the
* shared resource the next process having access is the one
* that asked immediately after (and, thus, had to wait) the
* writer process.
* A complete waiting queue is implemented with a Vector, where index
* i indicates the i_th access request. Thus, the Vector reflects the
* order in which access requests have been made to this server.

remoteClassv7.java
* This is "Version 7 server" i.e.:
* Fix a "low probability error" for version 6, since on accessReader()
* after the code (lines 81-98)
* synchronized (this)
* {
* ...
* waitingProcesses.addElement(waitingreader);
* ...
* }
*
* another thread could execute on leaveWriter() (line 199)
*
* synchronized(waitingProcesses.firstElement()) { waitingProcesses.firstElement().notify(); } // Wake up a reader
*
* and the reader is not really waiting on the corresponding monitor
* object. This is because monitors are not semaphores (ok, already
* known). Thus, semaphores should be used, since they hold "permits"
* instead of being "mutexed" by the JVM as monitors are.
* In this version, the vector of waiting processes holds semaphores
* instead of objects (monitors) thus when a process calls acquire()
* instead of wait(), the semaphore has "memory" if a previous
* release() has been made, and this is not the behaviour of notify(),
* since a notify() whithout a previous release does not imply anything.
* Why is it possible that another thread execute on leaveWriter? Well,
* it's because synchronized (this) releases the monitor and other
* process is now allowed to continue/enter the "synchronized" code of
* this object.


tocompile: shell script to compile everything (including several non
necessary remoteClassv<i>). Used with
./tocompile
Uncomment the line with the rmic command if running with jre previous
to version 1.5


torunask: shell script to start a "client" object (the one making the
rmi).Used with
./torunask <Read/Write>
where Read ==> start a reader process
where Write ==> start a writer process


torunremote: shell script to start a "server" object (the one with the
remote object to be rmi'ed). In fact, this script starts the
rmiregistry as well. Used with
./torunremote
CAUTION: this script ends only with ^C or kill, and the rmiregistry
should be ended by something like
killall rmiregistry


Install on a single computer
----------------------------
(Enough to see the different "server" behaviors)

1) Untar the file:
tar -xvf rmirw.tar

2) Go to the proper directory
cd rmirw

3) Compile every source file (uncomment the the line with the rmic
command if running with jre previous to version 1.5):
./tocompile

4) Start the server process on a terminal:
./torunremote

(the server version/behavior is hardcoded in the file startRemoteObject.java)


Running experiments (different number/sequence of readers-writers)
--------------------------------------------------------------------

Start as many readers/writers as needed for an experiment (and in the proper
sequence):
./torunask Read
(a reader process is started)

./torunask Write
(a writer process is started)

Since every process displays some (ore many) messages, it is recommended to start
each one of them on a different terminal on some X interface in order to see the
evolution. If the 5 hardcoded seconds are too small/large for clients (readers
and/or writers), just change the lines 75 and/or 84

Thread.currentThread().sleep(5000);

on askRemote.java and recompile. The file Screenshot.png shows a run with two
reader processes and a writer process, started in the sequence:
reader - writer - reader


Experimenting with different server versions
--------------------------------------------

Change line 47

remoteClassv<i> robject = new remoteClassv<i>();

on startRemoteObject.java with the proper "i" (i = 1, 2, ..., 7), recompile
and run as explained above ("Running experiments...")


Installing on different computers
---------------------------------

Follow the steps of "Install on a single computer" above or just copy .class
files in each host to be used.


Experimenting with different computers
--------------------------------------

Follow the steps above on "Running experiments..." and "Experimenting with
different..." and change line 35

java askRemote localhost $1

on torunask replacing "localhost" by the name of the host (or its IP number)
on which the torunremote is running.

Report bugs/comments: ftinetti @ gmail . com (remove whitespaces), with subject "rmirw"