// This file defines class "SharedDataStruct", a shared data structure which is // accessed by reader and writer threads. // // In this small example, the "shared data" consists of a single integer. // This integer is declared to be private to class SharedData. The only // way for readers and writers to access this integer is by calling the // data access methods "dataRead" and "dataWrite". The reader/writer // synchronization is built into the data access methods. (The implementation // of dataRead and dataWrite uses calls to the rw monitor, to provide // synchronization.) // // From the outside, the reader and writer threads using the SharedData // class do not need to be aware that there is any synchronization going on. // This is a "safe" way to organize the software, with no chance that a // reader or writer could access the data illegally. For example, it is // impossible for a reader to "forget to call startRead". The only way a // reader can access the shared data is via method "dataRead". If the reader // tries to access dataValue directly, a compile-time error results, since // dataValue is declared to be private. // // In a more realistic example, a complex data structure would be declared // instead of the integer dataValue. This complex data structure (still // declared "private") would be accessed via set of data access methods, with // one data access method for each type of update or value-retireval that // can be done. // // The data access methods (dataRead and dataWrite) use sleep statements // to simulate the time taken to access a complex database. This allows // us to observe the synchronization between readers and writers. // This code uses class rwMonitor. public class SharedDataStruct { // For this small example, the "shared data" consists of a single integer private int dataValue; // Declare an instance of the reader-writer monitor, to synchronize access // to dataValue. If several instances of SharedDataStruct are created // (e.g. in mainMethod), then each of these data structures has its own // instance of the reader-writer monitor. That way, the synchronization // for "access to data structure number one" is not affected by // synchornization for access to "data structure number two". private rwMonitor rw; // The constructor for class SharedDataStruct. public SharedDataStruct() { dataValue = 0; // Initialize the "shared data" rw = new rwMonitor(); } // end of the constructor for class SharedDataStruct // --------------------- Data Access Methods ---------------------------- // The dataWrite method changes the value of some part of the shared // data. In this small example, the integer value is updated. // A sleep statement simulates the time taken to update shared data that // has a more complicated structure. public void dataWrite (int value) { rw.startWrite(); dataValue = -30; // This value represents that "the database is being // updated". No reader should ever see this value. try { Thread.sleep((int)(200*Math.random()+1)); } catch(Exception e) { } dataValue = value; rw.endWrite(); } // end of the dataWrite method // The dataRead method reads some part of the shared data. In this small // example, the integer value is read. // A sleep statement simulates the time taken to access shared data that // has a more complicated structure. Reading takes half as long as writing. public int dataRead () { int value; // the value read from the shared data. rw.startRead(); try { Thread.sleep((int)(100*Math.random()+1)); } catch(Exception e) { } value = dataValue; rw.endRead(); return value; } // end of the dataRead method } // end of class "SharedDataStruct"