在 Windows 上的 Java 中并发文件写入

2022-09-03 01:38:41

在同一文件上同时打开两个(或多个)FileOutputStreams 时,会发生什么情况?

Java API是这样说的:

特别是某些平台,一次只允许一个 FileOutputStream(或其他文件写入对象)打开文件以进行写入。

我猜Windows不是这样的平台,因为我有两个线程读取一些大文件(每个线程是不同的),然后将其写入相同的输出文件。不会引发异常,文件已创建,并且似乎包含来自两个输入文件的块。

题外问题:

  • Unix也是如此吗?
  • 由于我希望行为是相同的(实际上我希望一个线程正确写入,另一个线程被警告冲突),我如何确定文件已经打开进行写入?

答案 1

当文件有另一个写入器时,没有一种可靠的跨平台方法来被动地收到通知 , 即,如果文件已经打开进行写入,则引发异常。但是,有几种技术可以帮助您主动检查这一点。

如果多个进程(可以是 Java 和非 Java 的混合)可能正在使用该文件,请使用 FileLock。成功使用文件锁的关键是记住它们只是“建议”。如果您检查锁,则保证它是可见的,但是如果您忘记了,它不会阻止您对文件执行操作。访问该文件的所有进程都应设计为使用锁定协议。

如果单个 Java 进程正在处理该文件,则可以使用 Java 中内置的并发工具来安全地执行此操作。您需要一个对将每个文件名与其相应的锁定实例相关联的所有线程可见的映射。可以轻松调整相关问题的答案,以便对对象或文件的规范路径执行此操作。lock 对象可以是 流周围的某个包装器,也可以是 ReentrantReadWriteLockFileFileOutputStream


答案 2

我会谨慎地让操作系统为您确定文件状态(因为这是依赖于操作系统的)。如果你有一个共享资源,我会使用重入锁来限制对它的访问

使用此锁意味着一个线程可以获取资源(文件)并写入它。下一个线程可以检查此锁是否由另一个线程持有,和/或无限期阻止,直到第一个线程释放它。

Windows(我认为)将限制两个进程写入同一文件。我不相信Unix会做同样的事情。