📄 readme
字号:
Readers/Writers on Java RMI---------------------------Readme/index.html file----------------------Copyright (C) 2007 Fernando G. TinettiDifferent ways for solving the readers/writers problems in thecontext of rmi, i.e., having an "access" server implemented withrmi. This server is used just for controlling the access to theshared 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 JavaAll of the versions are defined separately trying to be self containedEvery 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()respectivelyIn 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 fileremoteMethod.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 RemoteExceptionstartRemoteObject.java: the class having a main() to createand 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 startRemoteObjectaskRemote.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 processremoteClassv<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 ./tocompileUncomment the line with the rmic command if running with jre previous to version 1.5torunask: shell script to start a "client" object (the one making thermi).Used with ./torunask <Read/Write>where Read ==> start a reader processwhere Write ==> start a writer processtorunremote: shell script to start a "server" object (the one with theremote object to be rmi'ed). In fact, this script starts the rmiregistry as well. Used with ./torunremoteCAUTION: this script ends only with ^C or kill, and the rmiregistry should be ended by something like killall rmiregistryInstall on a single computer----------------------------(Enough to see the different "server" behaviors)1) Untar the file: tar -xvf rmirw.tar2) Go to the proper directory cd rmirw3) Compile every source file (uncomment the the line with the rmic command if running with jre previous to version 1.5): ./tocompile4) 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 propersequence): ./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 starteach one of them on a different terminal on some X interface in order to see theevolution. 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 tworeader processes and a writer process, started in the sequence: reader - writer - readerExperimenting with different server versions--------------------------------------------Change line 47 remoteClassv<i> robject = new remoteClassv<i>();on startRemoteObject.java with the proper "i" (i = 1, 2, ..., 7), recompileand run as explained above ("Running experiments...")Installing on different computers---------------------------------Follow the steps of "Install on a single computer" above or just copy .classfiles in each host to be used.Experimenting with different computers--------------------------------------Follow the steps above on "Running experiments..." and "Experimenting withdifferent..." and change line 35 java askRemote localhost $1on torunask replacing "localhost" by the name of the host (or its IP number)on which the torunremote is running.LicenseThis code is released under the GNU GPL version 2 or any later version. http://www.gnu.org/copyleft/gpl.html
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -