- PR -

ディレクトリの排他制御

投稿者投稿内容
どんたくお
ベテラン
会議室デビュー日: 2005/08/29
投稿数: 88
投稿日時: 2007-03-09 17:18
coasmさま

ご教授いただきましたように、synchronizedにて制御してみましたが、
こちらのRedHatLinux ES4では、排他制御かからないようです。
以下、コードです。

コード:
public class Lock {
	private FileChannel chanel;
	private FileLock lock;
	
	// Windowsは"C:/tmp/hoge.lock";
	private final File file = new File("/tmp/hoge.lock");
	
	public void t() throws IOException {
		try {
			try {
				lock();
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				// ignore...
			}
		} finally {
			unlock();
		}
		

	}
	
	private synchronized void lock() throws IOException {
		RandomAccessFile ra = new RandomAccessFile(file, "rw");
		// 排他ロックをかけます。
		chanel = ra.getChannel();
		lock = chanel.tryLock();
		if (lock == null) {
			throw new IOException("ロックです。");
		}
		System.out.println("ロックしました。");
	}
	
	private synchronized void unlock() throws IOException {
		if (chanel.isOpen()) {
			if (lock != null) 
				lock.release();
			chanel.close();
		}
	}
}



↑を書きまして、
test.jsp
コード:
	new Lock().t();



とします。

そして、ブラウザを二つ立ち上げて、test.jspに同時にアクセスすると
Windowsでは、ロックです。というエラーレポートが出力され正常に
排他制御かかっているのですが、Linuxだと、
ロックしました
と2回標準出力に表示されます。

自分のsynchronizedブロックの使い方が悪いのが原因かもしれません。


引き続きまして、ご教授いただけると幸いです。
どんたくお
ベテラン
会議室デビュー日: 2005/08/29
投稿数: 88
投稿日時: 2007-03-09 17:34
Tdnr_Symさん、かつのりさん、ご返信いただきましてありがとうございます。

> java.util.concurrent.Semaphore
> これって使えないんですかね?
なるほど。
少し、Google先生に聞いてみたのですが、参考になるページが見つかりました。
もう少し調べてみて、検証をしてみたいと思います。

> VMより上位の層のロック取得ができないと、
> クラスタ時で困りますね。
自分は、クラスタ時のことは見目想定しておりませんでした・・・。


今回、排他制御を自分で実装してみて初めて、その難しさを感じました。
データ操作は、ほとんどデータベース任せなのですが、そういうことばかり
していると、こういうときに自分で実装できませんね・・・。
データベースのありがたみと、自分の無知を改めて感じました。

精進したいものです。
会議室デビュー日: 2006/10/17
投稿数: 13
投稿日時: 2007-03-10 00:40
引用:

どんたくおさんの書き込み (2007-03-09 17:18) より:
コード:
private synchronized void lock() throws IOException {




は、同一オブジェクトのみ同期します。けっして同一クラスではありません。

Windowsは、運よく動いたのかな。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-03-10 12:04
比較的高速な処理のためにI/Oを使用するロックはコストが高すぎますが、
I/O処理の為のロックであれば、DBを使うのもありでしょう。

------------------------------------------------------------------------
1.ロックテーブルを用意
    例えば、locktable(key int, locked bit)
2.指定のキーかつlockedがfalseという条件で、
    select/for updateで行ロックを取得して、lockedをtrueに更新、コミット
3.2の処理に失敗したらロック失敗、成功したらロック成功とする
4.本処理が終わればlockedをfalseに更新

ロックしたまま例外で何も出来なくなったとき用に、
日付カラムを持って、一定の期間という条件を追加するというのもあり。
------------------------------------------------------------------------


という感じでDBのロックを使うのもありかなと思います。
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-03-10 17:04
synchronizedキーワードはまずは単体で意味を理解するのが重要だと思っています。
メソッドにsynchronizedキーワードをつけるのはいわゆるシンタックスシュガーですね。

コード:
synchronized(ロックオブジェクト) {
    // 同期処理
}


というのが基本です。
ロックオブジェクトはObjectのインスタンスであれば何でもかまいません。
Objectはロックをもっていて、それをスイッチにして排他しているイメージ。

非staticなメソッドにsynchronizedキーワードをつけた場合は
該当インスタンスをロックオブジェクトとしてsynchronized句を書くのと同等。

staticなメソッドにsynchronizedキーワードをつけた場合は
該当クラスのClassインスタンスをロックオブジェクトとして
synchronized句を書くのと同等になります。

コード:
public class Hoge {
   // 非staticの場合
   private synchronized void hoge() {
      ...
   }
   private void hoge() {
      synchronized (this) {
         ...
      }
   }

   // staticの場合
   private static synchronized void hoge() {
      ...
   }
   private static void hoge() {
      synchronized (Hoge.class) {
         ...
      }
   }
}

スキルアップ/キャリアアップ(JOB@IT)