Windows против OSX FileLock OutputStreamWriter

Я написал Java-приложение, которое обращается к файлу, в то время как другие процессы на других виртуальных машинах пытаются сделать то же самое. Поэтому я использую класс FileLock:

FileOutputStream fos = new  FileOutputStream(filePath,append);
    FileChannel f = fos.getChannel();
    FileLock lock;

    while ((lock = f.tryLock()) == null){
        try {
            Thread.sleep(100);
        } catch (InterruptedException ex) {
            Logger.getLogger(Util.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    OutputStreamWriter out = new OutputStreamWriter( new FileOutputStream(filePath,append));
    out.write(textToWrite);
    out.close();
    lock.release();

Все отлично работает на Mac OSX, но когда я запускаю код в Windows 7, он выдает IOException в строке

out.close();

, при попытке смыть.

java.io.IOException: The process cannot access the file because another process has locked a portion of the file
at java.io.FileOutputStream.writeBytes(Native Method)

Насколько я понимаю из Как работает FileLock?, фактическое получение блокировки с

f.tryLock()

запрещает мне доступ к нему, так как другой процесс (по-видимому, этот) имеет эксклюзивную блокировку.

Теперь это кажется мне парадоксом - как я могу получить монопольную блокировку, чтобы позволить мне писать в файл без опасности того, что другие процессы возятся с ним, в то время как фактический акт получения блокировки мешает мне сделать это?

И, следовательно, почему это работает на Mac OS, а не на Windows? Из JavaDocs я знаю, что с классом FileLock есть различия и трудности, характерные для ОС, но, конечно же, не в отношении его предназначенной для него функциональности. Поскольку этого не может быть, я делаю что-то не так, и здесь я прошу вашей помощи.

Спасибо, М


person Mathew    schedule 20.02.2013    source источник


Ответы (1)


В UNIX нет блокировки файлов.: http://www.coderanch.com/t/551144/java/java/File-lock-doesn-prevent-threads. Фактически, в UNIX вы можете удалить файл из-под процесса, и он может даже не заметить...
Поэтому вам нужно использовать файл блокировки, существование которого вы можете проверить.
Парадоксальным образом ваш код работает в Windows, но не в UNIX (т.е. Mac OS), исключение должно быть ожидаемым результатом попытки записи в файл, заблокированный другим процессом.

person Boris the Spider    schedule 20.02.2013
comment
Спасибо за ваш ответ. Однако я не уверен, что полностью понимаю вас и сообщение coderanch. Вы имеете в виду, что нет блокировки файлов, что UNIX не предоставляет функциональность, и поэтому я должен предоставить ее с помощью класса FileLock? И, следуя вашему аргументу, Windows предоставляет функциональность блокировки файлов, и поэтому мне не нужно использовать FileLock? Если я вас понимаю, то это даже делает шаг вперед, и попытка использовать FIleLock в Windows вызывает исключение? - person Mathew; 20.02.2013
comment
Класс FileLock очень специфичен для ОС - в UNIX он абсолютно ничего не делает; что, админ, несколько бесполезно. В Windows у него есть свои проблемы, как в упомянутом вами посте. Короче говоря, это немного изворотливый. Поэтому я бы рекомендовал использовать файл блокировки, т.е. что-то куда-то записать и использовать как внешний мьютекс. - person Boris the Spider; 20.02.2013
comment
У вас есть больше доказательств этого, чем только эта статья? Простите за лицемерие, но я не считаю coderanch.com особенно надежным, так как я видел там значительное количество дезинформации. Если методы блокировки файлов на самом деле не вызывают базовую функцию flock() или lockf() системы Unix или какую-то эквивалентную, почему возникают такие ошибки, как Ошибка Java 4877242 (блокировки файлов на поток в Linux)? - person VGR; 20.02.2013
comment
Информации очень много, но это в интернете. Что-то на форумах Ubuntu, другая статья с тестовыми примерами, которые вы можете попробовать, и отчетом об ошибке Oracle — это старо, но объясняет основную проблему. Надеюсь, это поможет. - person Boris the Spider; 20.02.2013