【发布时间】:2014-01-19 21:26:04
【问题描述】:
我正在尝试制作一个运行多个并行读取器和写入器的程序。我使用ExecutorService 类在循环中启动一些线程,Writer 类的run() 方法只调用两个方法StartWrite() 和EndWrite() 以及Reader 类StartRead() 和EndRead()。这些方法封装在监视器中。
这是监视器:
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(); }
}
但是有一个问题:程序在写入和读取预期数量的数据之前就结束了。例如,如果我启动 20 个写入器和 20 个读取器线程,我希望写入和读取 20 个数字,但只有 10~ 是。如果我再次运行程序(datos.dat 已经创建),它会继续写入和读取,然后写入 20 个数字。
测试:
第一次运行
- 写在最后执行的线程中:0 1 2 3 4
- 读入最后执行的线程:0 1 2 3 4
第二次运行
- 写在最后执行的线程中:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
- 读入最后执行的线程:0 1 2 3 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
怎么了?我怎样才能让它正常工作?
编辑:我尝试在每次读者完成阅读时打印读者数量,并且多次打印相同数量的读者。这不不应该发生吗? readers-- 在代码的受锁保护部分执行。
【问题讨论】:
-
您能否确保它确实在运行,
toWrite.wait()和toRead.wait()会在此处抛出IllegalMonitorStateException,除非您没有向我们展示更多代码。 -
检查我的答案的结尾,关于您的编辑。
-
你是对的,那些异常被抛出了,我捕捉到了错误的异常,所以似乎没有抛出任何异常。
-
@dabadaba 我推荐的两件事是 1. 使用
await而不是wait2. 让它坐在while(writing || reading)而不是 if -
我认为在使用类 Condition 时不需要使用,而 ifs 工作得一样好,但效率更高。
标签: java multithreading file concurrency monitor