1

ウェブサイトでページがリクエストされるたびに、次のようなサービスコールで詳細を記録します。

logService.logPageRequest(session, request, contentId);

このサービス呼び出しは、静的FileUtils(私自身の)メソッドを使用して、ファイルの実際の更新を行います。

public static void appendToTextFile(String string, String fileRootDirectory, String subdirectory, String filename, boolean startOnNewLine) throws Exception {
    // code irrelevant to the question removed

    String filePath=fileDirectory+"/"+filename;
    File file=new File(filePath);
    if(file.exists()) {
        FileWriter out = new FileWriter(filePath, true);
        if(startOnNewLine) {
            out.write("\r\n");
        }
        out.write(string);
        out.close();
     } else {
         FileWriter out = new FileWriter(filePath);
         out.write(string);
         out.close();
}

時々(たとえば15分ごとにスケジュールされます)、このファイルの名前を変更して処理を開始する別のサービスを実行します。

両方の同時書き込みが安全であり、書き込みの処理中に名前変更が実行されないようにする方法を理解したいと思います。答えは何らかの形の同期になると思います。

4

1 に答える 1

2

2つのサービスは同期オブジェクトを共有する必要があります。同期オブジェクトは何でもかまいnew byte[1]ませんが、「サービス」に渡される1つの同じインスタンスである必要があります。共有リソースを操作したいコードの一部を意味するクリティカルセクションがあるときはいつでも、それをラップする必要があります

synchronized(theInstanceOfSynchronizationObject) {
  // ... your code for critical section
}

適切なロックのルールは、何をロックしているのか、正確には何が共有リソースであるのかを決定論的に知ることです。あなたを殺す(そしてデッドロックを引き起こす)のは、「解決」を期待して同期されたブロックをランダムに追加することです。あなたの特定の例では、それはおそらくfileアクションだけであり、ファイル名文字列の操作ではなく、:のインスタンス化でもありません。ディスク上の同じファイルを指すFile多くのオブジェクトを持つことができ、それが重要な操作である限り、それは重要な操作ではありません。まだディスクに触れていません。だから私は言うだろうFile

File file=new File(filePath);
synchronized(theInstanceOfSynchronizationObject) {
  if(file.exists()) {
  } else {
  }
}

同様に、他のサービスのFile アクションを保護します。File保護しているのはオブジェクトではなく、ファイル自体であることに注意してください。

于 2012-11-19T09:44:25.447 に答える