Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Синхронизация доступа, к файлу 
:(
    Опции темы
zss
Дата 12.2.2005, 23:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: нет
Всего: 2



Есть 2 потока. Один читае файл, а другой пишет. Как синхронизировать доступ к файлу ?
PM MAIL ICQ   Вверх
LSD (Online)
Дата 13.2.2005, 00:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Простейший способ, хотя и не самый оптимальный:
Код
Object LOCK = new Object();
....
synchronized(LOCK)
{
//делаем здесь ВСЕ манипуляции с файлом
}

Есть еще варианты, но надо смотреть по задаче, надо ли уведомлять читающий процесс о новых данных, надо ли на это время останавливать запись в файл и т.д.

Это сообщение отредактировал(а) LSD - 13.2.2005, 00:12


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
zss
Дата 13.2.2005, 09:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: нет
Всего: 2



Смысл такой - читающий поток проверяет дату последнего изменения файла. Если она изменилась, то он читает его. Пишуший поток просто пишет через определенные период времени.
PM MAIL ICQ   Вверх
Domestic Cat
Дата 13.2.2005, 10:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 50
Всего: 172



Тогда можно сделать как LSD предлагает, только учти что lock должен быть один и тот же для обеих тредов

Код

public static final Object LOCK = new Object();

...
// тред 1
synchronized(LOCK)
{
  проверяем дату
}
...
// тред 2
synchronized(LOCK)
{
    пишем в файл
}



--------------------

PM   Вверх
zss
Дата 13.2.2005, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: нет
Всего: 2



Наверное так не получится - эти потоки находятся в разных приложениях.

Тоесть они могут запускаться независимо друг от друга.

Может это можно сделать средствами самого файла ?
PM MAIL ICQ   Вверх
LSD (Online)
Дата 13.2.2005, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Цитата(zss @ 13.2.2005, 10:41)
Может это можно сделать средствами самого файла ?

Для чтения использовать RandomAccessFile и открывать файл на запись, если в этот момент в файл пишет другая программа, то будет ошибка.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
djGri
Дата 21.2.2005, 18:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 77
Регистрация: 21.2.2005

Репутация: 1
Всего: 3



public void syncronized read() throws .... {
// insert code here
}
public void syncronized write() throws ....{
// insert code here
}
PM MAIL   Вверх
Domestic Cat
Дата 21.2.2005, 18:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 50
Всего: 172



Цитата
public void syncronized read() throws .... {
// insert code here
}
public void syncronized write() throws ....{
// insert code here
}


Все это не должно принадлежать этим двум тредам.

Пожалуйстa пользуйся тегами [codе=javа] [/code].


--------------------

PM   Вверх
Zandr
Дата 26.2.2005, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 433
Регистрация: 16.7.2004
Где: Новосибирск

Репутация: 9
Всего: 13



Цитата
Есть 2 потока. Один читае файл, а другой пишет. Как синхронизировать доступ к файлу ?

Цитата
Наверное так не получится - эти потоки находятся в разных приложениях.
Тоесть они могут запускаться независимо друг от друга.

Пока не оказалось, что это вообще разные файлы на разных машинах, предложу следующее (это просто кусок из моего кода, не адаптированный под текущий вопрос):
Код

...
FileInputStream fis = new FileInputStream( ...);
FileChannel chan = fis.getChannel();
FileLock lock = chan.tryLock(0, Long.MAX_VALUE, true);
if (lock == null) {
   System.out.println( "Другой процесс использует файл");
} else {
   ...
   lock.release();
}
fis.close();
...


Это сообщение отредактировал(а) Zandr - 28.2.2005, 14:30
PM MAIL   Вверх
Guest
Дата 28.2.2005, 09:24 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Цитата(Zandr @ 26.2.2005, 10:20)
Пока не оказалось, что это вообще разные файлы на разных машинах


smile

Это один файл на одной машине (PC1), но читатель и писатель на разных (PC2 и PC3)

Тоесть участвуют 2 разные машины для манипуляцией файлом, а сам он лежит на третьей (например на сервере)

  Вверх
zss
Дата 28.2.2005, 09:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: нет
Всего: 2



извиняюсь - не зашел smile
PM MAIL ICQ   Вверх
Zandr
Дата 28.2.2005, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 433
Регистрация: 16.7.2004
Где: Новосибирск

Репутация: 9
Всего: 13



Значит юзай блокировки на уровне файловой системы, как в примере выше (я его попровил немного). Там осуществляется попытка блокировки на запись. Остальное в API.
PM MAIL   Вверх
zss
Дата 28.2.2005, 16:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: нет
Всего: 2



Что-то не очень-то получается

если блокировать и читающий процесс и пишущий, то вроде все должно работать, но все равно слетает smile
PM MAIL ICQ   Вверх
Zandr
Дата 2.3.2005, 08:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 433
Регистрация: 16.7.2004
Где: Новосибирск

Репутация: 9
Всего: 13



Не, процессы блокировать не нужно. Блокировать нужно файлы smile Если твой процесс читает файл - есть смысл заблокировать файл на изменение, если твой процесс пишет в файл, то есть смысл заблокировать файл вообще. Естественно что нужно аккуратно все это делать. Заблокировать можно не весь файл, а только его часть. Блокировка (которая выше) работает не на уровне Java-машины, а на уровне операционки. Поэтому если блокируешь файл на доступ, то другие программы не могут его прочитать не зависимо от того на каком языке они написаны. Есть криво написанные программы, которые не блокируют файлы, обрабатывающиеся продолжительное время.

Цитата
все равно слетает

В какую сторону?
PM MAIL   Вверх
zss
Дата 12.3.2005, 15:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: нет
Всего: 2



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

Код

java.nio.channels.NonWritableChannelException
    at sun.nio.ch.FileChannelImpl.tryLock(FileChannelImpl.java:784)
    at java.nio.channels.FileChannel.tryLock(FileChannel.java:967)



Тестовый вариант

Код

public class Lock {

    private static String filePath = "C:\\test.txt";
    private static File file = new File (filePath);

    public Lock() {
        readFile();        
        writeFile();                
    }

    public void readFile (){

        try {

           
            FileInputStream stream = new FileInputStream ( file );
            FileChannel chan = stream.getChannel ();
            FileLock lock = chan.tryLock (0, Long.MAX_VALUE, true);
            if ( lock == null ) {
                System.out.println ( "Файл заблокирован на запись" );
                return;
            }
            else {
//                lock.release ();
//                chan.close();
//                stream.close ();
            }

        }
        catch ( Throwable t ) {
            t.printStackTrace ();
        }

    }

    public void writeFile(){
        try {

            StreamResult outStream = new StreamResult ( file );
            
            
            FileOutputStream stream = new FileOutputStream ( file );
            FileChannel chan = stream.getChannel ();
            FileLock lock = chan.tryLock ();
            if ( lock == null ) {
                System.out.println ( "Файл заблокирован на чтение" );
                return;
            }
            else {
//                stream.write(-1);
//                lock.release ();
//                chan.close();
//                stream.close ();
            }

        }

        catch ( Throwable ex ) {
            ex.printStackTrace ();
        }

    }


    public static void main(String[] args) {
        Lock lock = new Lock ();
    }

}



И самое главное. Это все работает при FileInputStream & FileOutputStream. Но мне надо при записи использовать StreamResult - а с ним к сожалению не получится получить FileChannel. Как быть ?

Думал прокатит так
Код

            FileOutputStream stream = new FileOutputStream (file);
            StreamResult out = new StreamResult ( stream );            
            FileChannel chan = stream.getChannel ();
            FileLock lock = chan.tryLock ();
            if ( lock == null ) {
                System.out.println ( "Файл заблокирован на чтение" );
                return;
            }
            else {
    transformer.transform ( source, out );
                lock.release ();
                chan.close();
                stream.close ();
            }



Но не дает писать - говорит файл заблокирован

P.S. Блин - задолбался с этой синхронизацией, что нельзя было просто сделать что-нибудь вроде Mutex

Это сообщение отредактировал(а) zss - 12.3.2005, 15:45
PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0962 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.