Reputation: 9512
I am trying to make a program that runs several parallel readers and writers. I start some threads in a loop using ExecutorService
class, the run()
method of the Writer class just call two methods StartWrite()
and EndWrite()
and for the Reader class, StartRead()
and EndRead()
. These methods are wrapped in a monitor.
Here's the monitor:
public class RWMonitorAN {
static int readers = 0;
static boolean writing = false;
public static RandomAccessFile f;
public static int n = 0;
private final ReentrantLock mylock = new ReentrantLock();
private final Condition toWrite = mylock.newCondition();
private final Condition toRead = mylock.newCondition();
public RWMonitorAN()
{
try { f = new RandomAccessFile("datos.dat", "rw"); } catch (IOException e) {}
}
void StartRead() {
mylock.lock();
try
{
if (writing)
try {
toRead.wait();
toWrite.wait();
} catch (InterruptedException e) {}
readers++;
try
{
f.seek(0);
while (f.getFilePointer()<f.length())
System.out.print(f.readInt()+" ");
System.out.println();
} catch (IOException e) { e.printStackTrace(); }
}
finally { mylock.unlock(); }
}
void EndRead() {
mylock.lock();
try
{
readers--;
if (readers == 0)
toWrite.signal();
}
finally { mylock.unlock(); }
}
void StartWrite() {
mylock.lock();
try
{
if (writing || readers != 0)
try {
toWrite.wait();
} catch (InterruptedException e) {}
writing = true;
try
{
f.writeInt(n);
} catch(IOException e) {}
n++;
}
finally { mylock.unlock(); }
}
void EndWrite() {
mylock.lock();
try
{
writing = false;
toWrite.signal();
toRead.signal();
}
finally { mylock.unlock(); }
}
But there's a problem: the program ends before the expected number of data is written and read. For example, if I start 20 writer and 20 reader threads, I expect 20 numbers to be written and read, but only 10~ are. If I run the program again (datos.dat would be already created) it keeps writing and reading and then 20 numbers are written.
Test:
1st run
2nd run
What's wrong? How can I make it work properly?
EDIT: I tried printing the number of readers every time a reader finishes reading and the same number of readers is being printed several times. Shouldn't this not be happening? readers--
is executed in a lock protected section of the code.
Upvotes: 1
Views: 141
Reputation: 2662
You are catching your exceptions everywhere and not reporting them anywhere nor do anything else to serve them. The first thing to "make it work properly" would probably be to check if there are exceptions called. For example, if you use more than one iterators on one data structure in Java it will probably throw concurrentModificationException at the start, to prevent unexpected behaviour in the future.
What is the point of using multiple readers from a file if, as it appears, you set every new one to the very beginning of a file with seek(0)? And your reader appears to try to read the whole file
while (f.getFilePointer()<f.length())
System.out.print(f.readInt()+" ");
and your writer tries to read a single int in
f.writeInt(n);
so if you started n threads I would not expect n numbers to be read.
Finally, have you considered what happens when you start another writer/reader after startRead unlocked mylock but before EndRead locked it again? Why not to put the logic from EndRead just at the end of startRead method then?
Upvotes: 0