Параллельная запись файла в Java на Windows
Что происходит, когда вы одновременно открываете два (или более) файла FileOutputStreams в одном файле?
API Java говорит следующее:
Некоторые платформы, в частности, позволяют открывать файл для записи только одним FileOutputStream (или другим объектом для записи файлов) за раз.
Я предполагаю, что Windows не такая платформа, потому что у меня есть два потока, которые читают большой файл (каждый другой), а затем записывают его в тот же выходной файл. Исключение не генерируется, файл создается и, как представляется, содержит куски из обоих входных файлов.
Боковые вопросы:
- Это тоже верно для Unix?
- И поскольку я хочу, чтобы поведение было одинаковым (на самом деле я хочу, чтобы один поток правильно писал, а другой - о конфликте), как я могу определить, что файл уже открыт для записи?
Ответы
Ответ 1
Не существует надежного кросс-платформенного способа пассивного уведомления, когда файл имеет другой файл сценария и т.д., например, создает исключение, если файл уже открыт для записи. Однако есть несколько методов, которые помогают вам активно проверять это.
Если несколько процессов (которые могут быть смешением Java и не-Java) могут использовать файл, используйте FileLock
, Ключом к успешному использованию блокировок файлов является помнить, что они только "консультативные". Блокировка гарантированно будет видна, если вы ее проверите, но это не помешает вам делать что-то в файле, если вы забудете. Все процессы, которые обращаются к файлу, должны быть разработаны для использования протокола блокировки.
Если один процесс Java работает с файлом, вы можете использовать инструменты concurrency, встроенные в Java, чтобы сделать это безопасно. Вам нужна карта, видимая для всех потоков, которая связывает каждое имя файла с соответствующим экземпляром блокировки. Ответ на связанный вопрос можно легко адаптировать для этого с помощью объектов File
или canonical пути к файлам. Объектом блокировки может быть FileOutputStream
, некоторая оболочка вокруг потока или ReentrantReadWriteLock
.
Ответ 2
Я бы опасался позволить ОС определить статус файла для вас (так как это зависит от ОС). Если у вас есть общий ресурс, я бы ограничил его доступ с помощью Блокировка повторного входа
Использование этой блокировки означает, что один поток может получить ресурс (файл) и записать на него. Следующий поток может проверить, не заблокирован ли этот замок другим потоком и/или блокировать неопределенно до тех пор, пока первый поток не освободит его.
Windows (я думаю) ограничит два процесса, записывающих один и тот же файл. Я не верю, что Unix сделает то же самое.
Ответ 3
Если 2 потока, о которых вы говорите, находятся в одной JVM, тогда вы можете иметь логическую переменную где-нибудь, к которой обращаются оба потока.
Ответ 4
Unix позволяет одновременным писателям в один и тот же файл.
Нельзя пытаться писать в один и тот же файл более одного раза. Если у вас есть дефект дизайна.