📄 remoteclassv5.java
字号:
/*################################################################################# remoteClassv5.java## Copyright (C) 2007 Fernando G. Tinetti## This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2 of the License, or# (at your option) any later version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License# along with this program; if not, write to the Free Software# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA################################################################################ * * 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. * Used from startService, which creates and registers one object of * this class. */import java.rmi.RemoteException; // For rmiimport java.rmi.server.UnicastRemoteObject; // For rmiimport java.lang.Thread; // For reporting thread idspublic class remoteClassv5 extends UnicastRemoteObject implements remoteMethod{ private int calls; // Just to count the number of rmi(nvocations) private int readers, writers; // Number of each kind of process currently accessing private int rwait, wwait; // Number of each kind of process currently waiting private int last; // Last process on the resource 0 ==> Reader, guess 1 private Object rqueue, wqueue; // Monitors used as queues protected remoteClassv5() throws RemoteException { super(); calls = 0; // no service provided so far readers = 0; // no readers accessing rwait = 0; // no readers waiting access writers = 0; // no writers accessing wwait = 0; // no writers waiting access last = 0; // assuming last access has been for readers rqueue = new Object(); // waiting queue for readers wqueue = new Object(); // waiting queue for writers } // ------------------- accessReader ------------------- public Boolean accessReader() throws RemoteException { System.out.println("Entering accessReader, wwait = " + wwait + " calls = " + calls + " thread " + Thread.currentThread().getId()); // Protect var. assignment from concurrent accesses synchronized(this) { calls++; } // Controlling access for readers while (readerHasToWait()) { // This has to be moved to readerHasToWait in order to avoid race conditions // rwait++; synchronized(rqueue) { try { rqueue.wait(); } catch(IllegalMonitorStateException e) { System.out.println("Exception IllegalMonitorStateException on accessReader on rqueue.wait()"); e.printStackTrace(); return Boolean.FALSE; } catch(InterruptedException e) { System.out.println("Exception InterruptedException on accessReader on rqueue.wait()"); e.printStackTrace(); return Boolean.FALSE; } } // The number of waiting readers go back to 0 when every waiting reader is awakened //rwait--; } // This reader gets the access // This has to be moved to readerHasToWait in order to "record" that a reader // has access so that writers can "see" it // readers++; // last = 0; System.out.println("Leaving accessReader, calls = " + calls + " thread " + Thread.currentThread().getId() + " readers: " + readers + " writers: " + writers); return Boolean.TRUE; } // ------------------- readerHaveToWait ------------------- protected synchronized Boolean readerHasToWait() { if (!((writers > 0) || ((wwait > 0) && (last == 0)))) { // This reader obtains the access readers++; last = 0; return Boolean.FALSE; } else { // This reader has to wait rwait++; return Boolean.TRUE; } } // ------------------- accessWriter ------------------- public Boolean accessWriter() throws RemoteException { System.out.println("Entering accessWriter, calls = " + calls + " thread " + Thread.currentThread().getId()); // Protect var. assignment from concurrent accesses synchronized(this) { calls++; } // Controlling access for writers while (writerHasToWait()) { // This has to be moved to readerHasToWait in order to avoid race conditions // wwait++; synchronized(wqueue) { try { wqueue.wait(); } catch(IllegalMonitorStateException e) { System.out.println("Exception IllegalMonitorStateException on accessWriter on wait()"); e.printStackTrace(); return Boolean.FALSE; } catch(InterruptedException e) { System.out.println("Exception InterruptedException on accessReader on wait()"); e.printStackTrace(); return Boolean.FALSE; } } // The number of waiting writers go back to 0 when every waiting reader is awakened //wwait--; } // This writer gets the access // This has to be moved to writerHasToWait in order to "record" that a writer // has access so that readers can "see" it //writers++; //last = 1; System.out.println("Leaving accessWriter, calls = " + calls + " thread " + Thread.currentThread().getId() + " readers: " + readers + " writers: " + writers); return Boolean.TRUE; } // ------------------- readerHaveToWait ------------------- protected synchronized Boolean writerHasToWait() { if (!((writers > 0) || (readers > 0) || ((rwait > 0) && (last == 1)))) { // This writer obtains the access writers++; last = 1; return Boolean.FALSE; } else { // This writer has to wait wwait++; return Boolean.TRUE; } } // ------------------- leaveReader ------------------- public Boolean leaveReader() throws RemoteException { System.out.println("Entering leaveReader, reader = " + readers + ", wwait = " + wwait); // This reader doesn't access anymore, blocking other processes that update the same var. // and, also, prevent "other" writers to get immediate access in case of waiting writers synchronized (this) { readers--; // Now, only waiting writers should be awakened if no more readers accessing if (readers == 0) { synchronized (wqueue) { try { // wakeup every waiting writer wqueue.notifyAll(); } catch(IllegalMonitorStateException e) { System.out.println("Exception IllegalMonitorStateException on leaveReader on notifyAll()"); e.printStackTrace(); return Boolean.FALSE; } } // No waiting writers on the wqueue (all of them have been awakened) wwait = 0; } } System.out.println("Leaving leaveReader" + " readers: " + readers + " writers: " + writers); return Boolean.TRUE; } // ------------------- leaveWriter ------------------- public Boolean leaveWriter() throws RemoteException { System.out.println("Entering leaveWriter"); // Blocking other processes that update/check values of shared variable/s synchronized (this) { // This writer doesn't access anymore writers--; // Do not give preference to any kind of process // Thus, every waiting process (readers and writers) should be awakened synchronized (wqueue) { try { // wakeup every waiting writer wqueue.notifyAll(); } catch(IllegalMonitorStateException e) { System.out.println("Exception IllegalMonitorStateException on leaveWriter on wqueue.notifyAll()"); e.printStackTrace(); return Boolean.FALSE; } } synchronized (rqueue) { try { // wakeup every reader waiting rqueue.notifyAll(); } catch(IllegalMonitorStateException e) { System.out.println("Exception IllegalMonitorStateException on leaveReader on rqueue.notifyAll()"); e.printStackTrace(); return Boolean.FALSE; } } // Every process is now trying to get access, not waiting rwait = 0; wwait = 0; } System.out.println("Leaving leaveWriter" + " readers: " + readers + " writers: " + writers); return Boolean.TRUE; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -