Top > MyPage
 

javaで同一ファイルを同時に操作させないために

ファイルロック

ウェブアプリに限らないが、ひとつのファイルを複数のユーザーで読み書きする場合、誰かがそのファイルにアクセスしている場合は、他者は触れないようにする必要がある。

今回、参考にしたページ

FileChannelをつかったロック

今やっているプロジェクトで、ひとつのファイルを同時に操作してしまい事故が発生する可能性があるので、実装した。

それを例にする

        
        
        //適当なロックファイル名
        File lockFile = new File(fileName+".lock");
        //仮想マシンが終了したら削除されるようにする
        lockFile.deleteOnExit();
        FileOutputStream fs = new FileOutputStream(lockFile);
        try {
            FileChannel ch = fs.getChannel();
            FileLock lock = null;

            final long TIMEOUT = 5000L; // timeout = 5sec
            final long WAIT = 100L;
            
            //指定されたファイルのロックを試みる
            //既に他者によってロックされている場合は100ミリ秒sleepする
            //最大5秒間は繰り返す
            for (int i = 0; i < (TIMEOUT / WAIT); i++) {
                if (null != (lock = ch.tryLock())) {
                    break;
                }
                Thread.sleep(WAIT);
            }
            if (null == lock) {
                return null;
            }

            try {
                // ファイルロックで同時に操作できないようしておいて、主目的の操作
                //今やっているプロジェクトでは、ファイルを読み込んで、
                //書いてある数字をカウントアップして、それを同じファイルに上書き保存する
                
            } finally {
                //用が済んだら必ずロックファイルを開放する
                lock.release();
                
                //FileChannelをクローズする。
                //このとき、ファイルロックされたままなら、そのファイルの開放も行われるので、
                //releaseはしなくても同じ
                ch.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            //FileOutputStreamをクローズ
            //もしかして、このときFileChannelもクローズされる?
            fs.close();
        }
          

以上のようにする。

要点は

  • FileChannelインスタンスを得る
  • そのインスタンスからtryLockメソッドでFileLockインスタンスを得る
  • FileLockインスタンスを持っている間はロックがかかっているので、目的の処理を行う
  • 用がすんだら、FileLockをreleaseして、FileChannelをcloseする