2012-04-06 13 views
2

次のメソッドは、共有変数にはアクセスしません。それでもスレッドセーフではありません。私は間違ってテストしているか、何か不足しています。説明してください。この静的Javaメソッドはスレッドセーフではないのはなぜですか?

方法:

public static boolean acquireFolderLock(File directoryPath) { 
    final String LOCK_FILE_NAME = ".lock"; 
    boolean isLocked = false; 
    if(directoryPath != null && directoryPath.isDirectory()) { 
     File lockFile = new File(new StringBuilder(directoryPath.getAbsolutePath()).append(File.separatorChar).append(LOCK_FILE_NAME).toString()); 
     if(lockFile.exists()) { 
      isLocked = false; 
     } else { 
      try { 
       lockFile.createNewFile(); 
       isLocked = true; 
      } catch(IOException ioex) { 
       isLocked = false; 
      } 
     } 
    } 
    return isLocked; 
} 

テスト

class AThread extends Thread { 
String name; 
public AThread(String name) { 
    this.name = name; 
} 

@Override 
public void run() { 
    File f = new File("C:\\TEMP\\DIRECTORY"); 
    System.out.println(name + ": " + Util.acquireFolderLock(f)); 
} 
} 

ためのThreadクラスとスレッド

public static void main(String[] args) throws Exception { 
    for(int i = 1; i <= 100; i++) { 
     (new AThread("Thread-->" + i)).start(); 
    } 
} 
+1

このメソッドがスレッドセーフではないとどのように判断していますか? –

+0

メインメソッドとテストスレッドクラスを追加しました – user1318311

+1

変数を共有していない可能性がありますが、状態を共有している可能性があります。 –

答えて

6

このメソッドは、ファイルが存在するかどうかをチェックし、後でそれを作成します。つまり、別のスレッドがlockFile.createNewFile();を実行しているときに、スレッドがif (lockFile.exists())(結果:false)のステートメントを実行した可能性があります(したがって、ロックファイルが作成されます)。

最初のスレッドは、ファイルが存在しないものの、既に別のスレッドによって作成されていると誤った情報に基づいて処理を継続しています。

スレッドセーフは共有変数だけではなく、共有リソース(変数、データベース、ファイルシステム、ネットワーク接続など)に関するものです。 File.createNewFileのJavadocによる

+0

ああ!その説明をありがとう。それは物事をクリアする。 – user1318311

3

は "静的状態" を開始する主な方法は、ファイルが含まれている用語システム。変数が明示的に共有されていないからといって、ファイルシステムがスレッド間で共有されているわけではありません。

ここでやっているやり方は、共有変数にアクセスするのと同じくらい悪く、スレッドセーフを作るために同じテクニックが必要です。

+0

申し訳ありませんが、詳しく説明できますか? Fileオブジェクトの代わりにStringというローカル変数を変更すると、このメソッドはスレッドセーフになりますか? – user1318311

+0

どちらの場合でも、同じスレッドセーフティ保証操作を追加する必要があることを意味します。 –

+0

@LouisWasserman引数が実際にStringであり、何も "外部データ"を呼び出さない場合、メソッドはすべての変数がローカルであり、パラメータが不変であるためスレッドセーフである。しかし確かにそれは多くのifsです;) – assylias

0

()http://docs.oracle.com/javase/6/docs/api/java/io/File.html#createNewFile()

注 得プロトコルを確実に動作させることができないように、この方法は、ファイルロックのために使用すべきではありません。 FileLock 機能を代わりに使用する必要があります。

スレッドセーフなjava.nio.channels.FileLockを使用する必要があります。

あなたがlockFile.createNewFile(の戻り値をチェックするためのものです)、あなたはlockFile.exists()も

true if the named file does not exist and was successfully created; false if the named file already exists 

をチェックする必要はありません

+0

同意します。指してくれてありがとう。 – user1318311

0

、あなたのユースケースに応じて、NIO FileLockがあるかもしれませんcreateNewFileを使用するよりも信頼性がありません。私はnio FileLockがNFS上で壊れていると思います。私はjavadocの意味が信頼できないのかどうかはわかりませんが、createNewFileの問題は、あなたがクラッシュしたときにロックを残してしまうことです。しかし、これはあなたのユースケースに応じてバグではなく機能になる可能性があります。

+0

これは、Javaロックだけでなく、NFS上で壊れているロックです。 – EJP

関連する問題