Одновременная запись файла в Java на Windows - PullRequest
17 голосов
/ 03 апреля 2009

Что происходит, когда вы одновременно открываете два (или более) FileOutputStreams в одном и том же файле?

Java API говорит следующее:

В частности, некоторые платформы позволяют открывать файл для записи только одним FileOutputStream (или другим объектом записи файла) за раз.

Я предполагаю, что Windows не такая платформа, потому что у меня есть два потока, которые читают какой-то большой файл (каждый по-своему), а затем записывают его в один и тот же выходной файл. Исключение не выдается, файл создан и, кажется, содержит фрагменты из обоих входных файлов.

Дополнительные вопросы:

  • Это правда и для Unix?
  • И поскольку я хочу, чтобы поведение было таким же (на самом деле я хочу, чтобы один поток записал правильно, а другой был предупрежден о конфликте), как я могу определить, что файл уже открыт для записи?

Ответы [ 4 ]

16 голосов
/ 03 апреля 2009

Не существует надежного кроссплатформенного способа пассивного уведомления, когда у файла есть другой создатель записи - то есть, вызвать исключение, если файл уже открыт для записи. Однако есть несколько методов, которые помогут вам активно проверить это.

Если файл может использоваться несколькими процессами (которые могут быть смесью Java и не-Java), используйте FileLock. Ключ к успешному использованию блокировок файлов - помнить, что они только «рекомендательные». Блокировка гарантированно будет видимой, если вы проверите ее, но она не помешает вам что-то сделать с файлом, если вы забудете. Все процессы, которые обращаются к файлу, должны быть разработаны для использования протокола блокировки.

Если с файлом работает один процесс Java, вы можете использовать встроенные в Java инструменты параллелизма, чтобы сделать это безопасно. Вам нужна карта, видимая всем потокам, которая связывает каждое имя файла с соответствующим экземпляром блокировки. Ответы на связанный вопрос можно легко адаптировать для этого с File объектами или каноническими путями к файлам. Объектом блокировки может быть FileOutputStream, некоторая обертка вокруг потока или ReentrantReadWriteLock.

4 голосов
/ 03 апреля 2009

Я бы не хотел, чтобы ОС определяла для вас статус файла (так как это зависит от ОС). Если у вас есть общий ресурс, я бы ограничил доступ к нему, используя Повторный вход блокировки

Использование этой блокировки означает, что один поток может получить ресурс (файл) и записать в него. Следующий поток может проверить, удерживается ли эта блокировка другим потоком, и / или блокировать неопределенно, пока первый поток не освободит ее.

Windows (я думаю) ограничит два процесса записи в один и тот же файл. Я не верю, что Unix сделал бы то же самое.

1 голос
/ 04 апреля 2009

Unix позволяет одновременно записывать в один и тот же файл.

Вы не должны пытаться записывать в один и тот же файл более одного раза. Если у вас есть недостатки дизайна.

1 голос
/ 03 апреля 2009

Если два потока, о которых вы говорите, находятся в одной и той же JVM, то у вас может быть где-то логическая переменная, к которой обращаются оба потока.

...