質問

書いう対応の同時読み取り/書き込み要求をデータベースファイルです。

ReentrantReadWriteLock のように見えいいます。すべてのスレッドのアクセスの共有 RandomAccessFile オブジェクトか心配しているファイルポインタとの兼ね!次のような例を考えてみましょう:

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Database {

    private static final int RECORD_SIZE = 50;
    private static Database instance = null;

    private ReentrantReadWriteLock lock;
    private RandomAccessFile database;

    private Database() {
        lock = new ReentrantReadWriteLock();

        try {
            database = new RandomAccessFile("foo.db", "rwd");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    };

    public static synchronized Database getInstance() {
        if(instance == null) {
            instance = new Database();
        }
        return instance;
    }

    public byte[] getRecord(int n) {
        byte[] data = new byte[RECORD_SIZE];
        try {
            // Begin critical section
            lock.readLock().lock();
            database.seek(RECORD_SIZE*n);
            database.readFully(data);
            lock.readLock().unlock();
            // End critical section
        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }

}

の①oai_dc()メソッドは、以下のインターリーブで複数の並行ですね。

スレッドの1->①oai_dc(0)
スレッドの2->①oai_dc(1)
スレッドの1>が取得で共有ロック
スレッドの2->が取得で共有ロック
スレッドの1->を記録0
スレッドの2->と記録1
スレッドの1->を読み込みを記録時のファイルポインタ(1)
スレッドの2->を読み込みを記録時のファイルポインタ(1)

がある場合にも可能性の並行処理における課題をReentrantReadWriteLockおよびRandomAccessFileは、その代替す。

役に立ちましたか?

解決

はい、このコードは、アウトラインと同じように、適切に同期されません。書き込みロックが取得されることはありません場合は読み書きロックは便利ではありません。何もロックが存在しないかのようにだ。

を使用しよう作成し、他のスレッドに、原子見える読み、またはシングルスレッドの排他的使用のために借りた後、返されsynchronizedインスタンスのプールを作成するために、伝統的なRandomAccessFileブロック。 (または、単にあなたがあまりにも多くのスレッドを持っていない場合は、各スレッドにチャンネルを捧げる。)

他のヒント

このロックファイルとロック解除ファイルというサンプルプログラムです。

try { // Get a file channel for the file 

    File file = new File("filename");

    FileChannel channel = new RandomAccessFile(file, "rw").getChannel(); // Use the file channel to create a lock on the file.

    // This method blocks until it can retrieve the lock. 

    FileLock lock = channel.lock(); // Try acquiring the lock without blocking. This method returns // null or throws an exception if the file is already locked. 

    try { 

        lock = channel.tryLock();

    } catch (OverlappingFileLockException e){}


    lock.release(); // Close the file 

    channel.close();
} 

catch (Exception e) { } 

あなたは代わりに独自のロックを管理するファイルシステムのロックを使用して検討する必要があります。

コールgetChannel().lock()クラス経由でファイルをロックするためにあなたのRandomAccessFileにFileChannel。これを防止も、あなたのコントロール外のプロセスから、書き込みアクセスを。

むしろ単一のロックオブジェクトではなく、方法で動作する、ReentrantReadWriteLockは65535の再帰的書き込みロックおよび65535の読取りロックの最大件までサポートすることができます。

を割り当て、読み取りと書き込みロック

private final Lock r = rwl.readLock();
private final Lock w = rwl.writeLock();

そして、それらの作業...

また:あなたは例外とロック後にロックを解除するために失敗のためにケータリングされていません。あなたは(ミューテックスロッカーのような)メソッドを入力すると、その後、最終的にはセクションのロックを解除してtry / catchブロックでの作業を行うロックを呼び出し例:

public String[] allKeys() {
  r.lock();
  try { return m.keySet().toArray(); }
  finally { r.unlock(); }
}

OK、8.5年間は長い時間が、あなたにとってどんな年でしたい刀...

私の問題としてアクセスするのに必要なストリームの読み書きとして原子として可能です。重要な部分した当社のコードは実行を複数のマシンにアクセスが同じファイルです。しかし、すべての事例は、インターネット止めする方法を説明するロック RandomAccessFile 僕はもっと深く。このような中、私ために Samの回答.

今からの距離のことは、あってはならないことでして、"物事には順序がある:

  • ロックファイル
  • の流れ
  • 何の流れ
  • ストリームを閉じ
  • ることでロックを解除できます

しかし、許可する、ロック解除にはJavaストリームを必ず閉じない!そのための全機構になっ(とは間違いだったのか?).

するために自動-閉会の仕事の一つは決して忘れてはいけないと思うJVMを閉じ、体の逆順にしています。この流れは以下のようなものです:

  • の流れ
  • ロックファイル
  • 何の流れ
  • ることでロックを解除できます
  • ストリームを閉じ

試験はこの方法でやらねばならない。そのため、自動閉半となり、good ol'Javaファッション1:

try (RandomAccessFile raf = new RandomAccessFile(filename, "rwd");
    FileChannel channel = raf.getChannel()) {
  FileLock lock = channel.lock();
  FileInputStream in = new FileInputStream(raf.getFD());
  FileOutputStream out = new FileOutputStream(raf.getFD());

  // do all reading
  ...

  // that moved the pointer in the channel to somewhere in the file,
  // therefore reposition it to the beginning:
  channel.position(0);
  // as the new content might be shorter it's a requirement to do this, too:
  channel.truncate(0);

  // do all writing
  ...

  out.flush();
  lock.release();
  in.close();
  out.close();
}

この方法は使用しなければならな synchronized.その他の並列処刑がスローする OverlappingFileLockException 通話の場合 lock().

ご経験の共有る場合がご---

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top