[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[jfriends-ml 10108] Re: Java 言語で学 ぶデザインパターン入門第 6 回議事録



こんばんは。武川です。

From: Murayama Toshikiyo <murayama@xxxxxxxxxxxxx>
Subject: [jfriends-ml 10107] Re: Java 言語で学ぶデザインパターン入門第 6 回議事録
Date: Tue, 07 May 2002 21:07:10 +0900

> > ええと、ひとつのスレッドがひとつのオブジェクトに対し複数回ロックを
> > 取得しようとした場合、1回目のロック取得と、2回目以降のロック取得と
> > では挙動が異なりますよね? 2回目以降は待たされないわけですから。
> #正確にはモニタというべきだと思う.ちなみに排他制御
> #機構としての「ロック」には二回目という概念はありません.
> 
> ##二回目をやったら,そのままデッドロックになるだけでは....
> 
> それと,待つ待たないってのはほとんど関係ないかと.

モニタはロックとそれを獲得しようとするスレッドの待機セット
で、オブジェクトが持っているものですから、
スレッドが取得しようとするのはロックではないでしょうか?

あと、同じスレッドが同じロックを獲得するのにデッドロック
になるかどうかは、ロックの実装によるはなしで概念ではない
と思うのですが、どうなんでしょうか?
#pThredとかはだめなんでしたっけ?

> 苦しいときのdeveloperworks頼み.
> http://www-6.ibm.com/jp/developerworks/java/020125/j_j-threads2.html#5
> #IBMはSUNと並んで最先端の最適化技術を持つ企業のひとつ.
> #この手の記事の信頼性は高いと思う.

<<ばっさり略>>

> これが正しいとすると,シングルCPUのマシン上では,これとは
> 異なる結果になるでしょう.

そうなのかよくわからないので、試してみました。
これもさらに混乱を増す結果なのですけど、試した結果をのせてみます。
まずソースです。

-----ここから-----
import java.util.*;

public class LockTest2 {

    public static void main(String args[]){
	LockTest2 test = new LockTest2();
	for(int i= 0;i<100000;i++){
	    test.v.add(Integer.toString(i));
	}

	for(int i=0;i<10;i++){
	    long start = System.currentTimeMillis(); 
	    test.getLongest2();
	    long time = System.currentTimeMillis() - start; 
	    System.out.println("getLongest2  time "+ time);
	    start = System.currentTimeMillis(); 
	    test.getLongest();
	    time = System.currentTimeMillis() - start; 
	    System.out.println("getLongest time "+ time);
	}

    }

    Vector v = new Vector();

    public String getLongest() {
	int maxLen = 0;
	String longest = null;

	for (int i=0; i<v.size(); i++) {
	    String s = (String) v.elementAt(i);
	    if (s.length() > maxLen) {
		maxLen = s.length();
		longest = s;
	    }
	}
	return longest;
    }

    public String getLongest2() {
	int maxLen = 0;
	String longest = null;

	synchronized (v) { 
	    for (int i=0; i<v.size(); i++) {
		String s = (String) v.elementAt(i);
		if (s.length() > maxLen) {
		    maxLen = s.length();
		    longest = s;
		}  
	    }  
	    return longest;
	}
    }

}
-----ここまで-----

村山さんの教えてくれたサイトのコード片を実行できるように
しただけです。で、100000個の要素を持つベクタを作って、
各メソッドを10回メソッドを呼びだします。

で、実行した結果がこちらです。

e:\project\java>java LockTest2
java LockTest2
getLongest2  time 10
getLongest time 110
getLongest2  time 40
getLongest time 111
getLongest2  time 40
getLongest time 100
getLongest2  time 40
getLongest time 110
getLongest2  time 40
getLongest time 100
getLongest2  time 40
getLongest time 110
getLongest2  time 40
getLongest time 101
getLongest2  time 40
getLongest time 100
getLongest2  time 30
getLongest time 110
getLongest2  time 40
getLongest time 100

もちろん、僕のマシンは1CPUです。うーん。なんでこないだのプログラム
は差がつかなかったのに、今度はついたのかわかりません。
#しかも平均しても2.5倍くらいはやくなっている。。。。

ちなみにgetLongestとgetLongest2の呼びだし順を変更しても同様です。
パフォーマンスチューニングの道は険しいみたいです。是非、他の
みなさんも試してみてください。あとバグがあれば教えてください。

個人的には、
「こんなバグがあったので直したところ、速度の差はありませんでした」
というのが整合性が取れるので嬉しいです。

ではでは。