并发读者 - 作家以一种意想不到的方式表现

时间:2014-01-02 12:17:05

标签: java multithreading file concurrency monitor

我正在尝试创建一个运行多个并行读取器和编写器的程序。我使用ExecutorService类在循环中启动一些线程,Writer类的run()方法只调用两个方法StartWrite()EndWrite(),而对于Reader类,{{1 }和StartRead()。这些方法包含在监视器中。

这是监视器:

EndRead()

但是有一个问题:程序在写入和读取预期数量的数据之前结束。例如,如果我启动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

怎么了?我怎样才能让它正常工作?

编辑:每次读者完成阅读并且多次打印相同数量的读者时,我都尝试打印读取器的数量。这个不应该发生吗? 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(); } } 在代码的受锁保护部分执行。

1 个答案:

答案 0 :(得分:0)

您到处都在捕捉您的例外情况,不会在任何地方报告,也不会做任何其他事情来为他们服务。 “使其正常工作”的第一件事可能是检查是否存在异常调用。例如,如果在Java中的一个数据结构上使用多个迭代器,它可能会在开始时抛出concurrentModificationException,以防止将来出现意外行为。

如果使用seek(0)将每个新文件设置到文件的最开头,那么从文件中使用多个阅读器有什么意义呢?而您的读者似乎试图阅读整个文件

 while (f.getFilePointer()<f.length())
                    System.out.print(f.readInt()+" ");

并且您的作者尝试在

中读取单个int

f.writeInt(n);

所以如果你开始了n个线程,我就不希望读取n个数字。

最后,您是否考虑过在startRead解锁mylock之后但在EndRead再次锁定它之前启动另一个编写器/阅读器时会发生什么?为什么不把startRead的逻辑放在startRead方法的末尾呢?