关于同时读取和写入文件的关注点是什么?
what are the concern regarding simultaneous read and write to a file?
考虑以下场景:
- 进程 1 (Writer) 连续向文件追加一行 (sharedFile.txt)
- 进程2(Reader)连续从sharedFile.txt
中读取一行
我的问题是:
在java中是否有可能:
- Reader 进程以某种方式崩溃 Writer 进程(即中断 Writer 进程)?
- Reader 一些如何知道何时停止读取文件的纯粹基于文件统计信息(Reader 不知道其他人是否正在写入文件)?
展示
进程一(作者):
...
while(!done){
String nextLine;//process the line
writeLine(nextLine);
...
}
...
进程二(Reader):
...
while(hasNextLine()){
String nextLine= readLine();
...
}
...
注意:
Writer 进程优先。所以没有什么可以干扰它。
代码不会崩溃。但是,reader 将在到达末尾时终止,即使作者可能仍在写作。您将不得不以某种方式进行同步!
关注:
您的 reader 线程可以读取过时值,即使您认为另一个编写器线程已更新变量值也是如此
如果不存在同步,即使您写入文件,您在读取时也会看到不同的值
Java 文件 IO 和纯文件不是为同时写入和读取而设计的。要么你的 reader 会赶上你的作家,要么你的 reader 永远写不完。
JB Nizet provided the answer in his comment. You use a BlockingQueue 在您阅读时保存作者数据。队列要么清空,要么 reader 永远不会完成。您可以通过 BlockingQueue 方法来检测这两种情况。
既然你说的是进程,而不是线程,答案取决于底层OS如何管理打开的文件句柄:
- 在我熟悉的每个 OS 上,Reader 永远不会使编写器进程崩溃,因为 Reader 的文件句柄只允许读取。在 Linux 上,系统调用 Reader 可能会在底层 OS 上调用
open(2)
,带有 O_RDONLY
标志,lseek(2)
和 read(2)
-- 已知不会干扰 Writer 正在调用的系统调用,例如 write(2)
.
- Reader 很可能不知道什么时候停止阅读大多数 OS。更准确地说,在某些读取尝试中,它将接收到零作为读取字节数,并将其视为 EOF(文件结尾)。就在这个时候,可能有Writer准备向文件追加一些数据,但是Reader无法知道。
如果你需要一种方法让两个进程通过文件进行通信,你可以使用一些额外的文件来实现,这些文件在 Readers 和 Writers 之间传递元信息,例如当前是否有 Writer 运行。在文件中引入一些结构也很有用(例如,每个 Writer 都会向文件附加一个字节,指示写入过程正在进行)。
对于非常快速的非阻塞 I/O,您可能需要通过 Java 的 MappedByteBuffer
.
考虑内存映射文件
考虑以下场景:
- 进程 1 (Writer) 连续向文件追加一行 (sharedFile.txt)
- 进程2(Reader)连续从sharedFile.txt 中读取一行
我的问题是:
在java中是否有可能:
- Reader 进程以某种方式崩溃 Writer 进程(即中断 Writer 进程)?
- Reader 一些如何知道何时停止读取文件的纯粹基于文件统计信息(Reader 不知道其他人是否正在写入文件)?
展示
进程一(作者):
...
while(!done){
String nextLine;//process the line
writeLine(nextLine);
...
}
...
进程二(Reader):
...
while(hasNextLine()){
String nextLine= readLine();
...
}
...
注意:
Writer 进程优先。所以没有什么可以干扰它。
代码不会崩溃。但是,reader 将在到达末尾时终止,即使作者可能仍在写作。您将不得不以某种方式进行同步!
关注:
您的 reader 线程可以读取过时值,即使您认为另一个编写器线程已更新变量值也是如此
如果不存在同步,即使您写入文件,您在读取时也会看到不同的值
Java 文件 IO 和纯文件不是为同时写入和读取而设计的。要么你的 reader 会赶上你的作家,要么你的 reader 永远写不完。
JB Nizet provided the answer in his comment. You use a BlockingQueue 在您阅读时保存作者数据。队列要么清空,要么 reader 永远不会完成。您可以通过 BlockingQueue 方法来检测这两种情况。
既然你说的是进程,而不是线程,答案取决于底层OS如何管理打开的文件句柄:
- 在我熟悉的每个 OS 上,Reader 永远不会使编写器进程崩溃,因为 Reader 的文件句柄只允许读取。在 Linux 上,系统调用 Reader 可能会在底层 OS 上调用
open(2)
,带有O_RDONLY
标志,lseek(2)
和read(2)
-- 已知不会干扰 Writer 正在调用的系统调用,例如write(2)
. - Reader 很可能不知道什么时候停止阅读大多数 OS。更准确地说,在某些读取尝试中,它将接收到零作为读取字节数,并将其视为 EOF(文件结尾)。就在这个时候,可能有Writer准备向文件追加一些数据,但是Reader无法知道。
如果你需要一种方法让两个进程通过文件进行通信,你可以使用一些额外的文件来实现,这些文件在 Readers 和 Writers 之间传递元信息,例如当前是否有 Writer 运行。在文件中引入一些结构也很有用(例如,每个 Writer 都会向文件附加一个字节,指示写入过程正在进行)。
对于非常快速的非阻塞 I/O,您可能需要通过 Java 的 MappedByteBuffer
.