17

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

Java API是这样说的:

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

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

附带问题:

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

4 回答 4

16

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

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

如果单个 Java 进程正在处理该文件,您可以使用 Java 内置的并发工具来安全地执行此操作。您需要一个对所有线程可见的映射,它将每个文件名与其对应的锁实例相关联。相关问题的答案可以很容易地调整为使用File对象或文件的规范路径来做到这一点。锁定对象可以是一个FileOutputStream,一些围绕流的包装器,或者一个ReentrantReadWriteLock.

于 2009-04-03T16:49:32.630 回答
4

我会警惕让操作系统为您确定文件状态(因为这取决于操作系统)。如果您有共享资源,我将使用可重入锁限制对它的访问

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

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

于 2009-04-03T11:28:28.143 回答
1

如果您正在谈论的 2 个线程在同一个 JVM 中,那么您可以在某个地方有一个两个线程都可以访问的布尔变量。

于 2009-04-03T11:40:16.930 回答
0

Unix 允许并发写入同一个文件。

您不应该多次尝试写入同一个文件。如果你是你有一个设计缺陷。

于 2009-04-03T20:30:26.373 回答