Захват файла Java

У меня есть несколько потоков (некоторые из которых порождены Процессом X, другими Процессом Y, и так далее), и каждый поток должен записать в файл MyFile. Однако, если Thread T1 начинает писать в MyFile во-первых, тогда, когда Thread T2 начинает писать, это должно ожидать T1 выпускать файл, так, чтобы это могло считать содержание, которое было записано в Thread T1. Другими словами, каждый поток имел бы a finalizeThread метод, как так:

private void finalizeThread() {
    File f = new File("MyFile.dat");
    f.createNewFile();  // atomically creates the file, if it doesn't exist
    locked_section {
        readContentsFromFile(f); // read contents if some other thread already modified the file
        modifyContentsFromFile(f); // modify
        writeFile(f); // write, so that new threads can see the content modified by this thread
    }
}

Мой вопрос: Как я могу выполнить locked_section в вышеупомянутом коде? Я изучал FileLock класс, но это говорит в Javadoc, что "Блокировки файла сохранены от имени всей виртуальной машины Java. Они не подходят для управления доступом к файлу несколькими потоками в той же виртуальной машине"..

12
задан João Silva 11 January 2010 в 23:48
поделиться

3 ответа

Если доступ к файлу осуществляется только из вашей программы, то объект синхронизированной блокировки в порядке. Но если вы хотите защитить файл от изменения другими программами во время работы над ним, вы можете использовать возможности Java-блокировки файлов в java.nio.channels.FileLock (example). Как сказано в тексте, помните, что на некоторых операционных системах программы все равно могут изменять файлы, если не проверять на наличие существующей файловой блокировки.

12
ответ дан 2 December 2019 в 21:02
поделиться

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

Все, что мы в итоге сделали:

  1. Каждый объект передается в C непрозрачной ручкой.
  2. Конструкторы и деструкторы заключены в чистые функции
  3. Членов функции являются чистыми функциями.
  4. Другие сборки отображаются на эквиваленты C, где это возможно.

Итак, такой класс, как этот (C++ заголовок)

class MyClass
{
  public:
  explicit MyClass( std::string & s );
  ~MyClass();
  int doSomething( int j );
}

Будет сопоставляться с C интерфейсом, таким как этот (C заголовок):

struct HMyClass; // An opaque type that we'll use as a handle
typedef struct HMyClass HMyClass;
HMyClass * myStruct_create( const char * s );
void myStruct_destroy( HMyClass * v );
int myStruct_doSomething( HMyClass * v, int i );

Реализация интерфейса будет выглядеть следующим образом (C++ источник)

#include "MyClass.h"

extern "C" 
{
  HMyClass * myStruct_create( const char * s )
  {
    return reinterpret_cast<HMyClass*>( new MyClass( s ) );
  }
  void myStruct_destroy( HMyClass * v )
  {
    delete reinterpret_cast<MyClass*>(v);
  }
  int myStruct_doSomething( HMyClass * v, int i )
  {
    return reinterpret_cast<MyClass*>(v)->doSomething(i);
  }
}

Мы извлекаем наш непрозрачный дескриптор из исходного класса, чтобы избежать необходимости в литье, и (Это, кажется, не работает с моим текущим компликером) Мы должны сделать дескриптор структурой, так как C не поддерживает классы.

Это дает нам базовый интерфейс C. Если вам нужен более полный пример, показывающий один из способов интеграции обработки исключений, то вы можете попробовать мой код на github: https://gist.github.com/mikeando/5394166

Теперь интересная часть гарантирует, что вы правильно получите все необходимые библиотеки C++, связанные в большую библиотеку. Для gcc (или clang) это означает, что выполняется только заключительная стадия связи с использованием g++.

-121--2043465-

Я думаю, iPhone правит разработкой оборудования и программного обеспечения, андроид интересен, но слишком новый, симбиам умирает, потому что Nokia, окна переживут причину денег с bull € & € &, но они будут. iPhone слишком ограничительный и чертовски дорогой, но это thecoolest сейчас. Наконец я думаю, что для NeXT 2 года iPhone будет царить.

-121--2740759-

Вместо совместного использования блокировки может потребоваться отдельный процесс, ответственный за сохранение блокировки файла. Чтобы начать ваш шаг чтения/изменения/записи, поток должен будет запросить этот центральный процесс блокировки через HTTP, сообщения или что угодно. Если запрос отклонен, поток перейдет в спящий режим, проснется и повторите попытку. В противном случае поток считывает/изменяет/записывает, а затем сообщает процессу блокировки, что снимает блокировку.

2
ответ дан 2 December 2019 в 21:02
поделиться

Вы захотите синхронизировать на каком-то объекте. Например:

synchronized(fileLockObject) {
    readContentsFromFile(f);
    modifyContentsFromFile(f);
    writeFile(f);
}
0
ответ дан 2 December 2019 в 21:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: