- - PR -
Javaのクラスメソッド(static)について
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2006-07-11 15:13
はじめまして。
いつも参考にさせて戴いております。 Javaのクラスメソッドに関してお聞きしたいのですが サーブレットの様な、不特定多数のアクセスを受け付けるアプリケーションを 作成する場合に、例えば名前に一律「さん」等の文字を付けるメソッドを クラスメソッドとして実装した場合には、クラスメソッドの特性からすると 一つのメソッドを、あらゆるオブジェクトと共有すると言うことなので 場合によっては (ロードアベレージ等で負荷がかかっている場合は処理の遅延等が発生し) データの競合(別なスレッドで登録した名前が表示されてしまう)が発生 するのでは無いかと懸念しておりますが、私の理解は間違えているでしょうか。 ※サーブレットで受け取ったリクエストを、サーブレット内部で下記の メソッドを実装したクラスを利用するイメージです。 ◆呼び出し側(サーブレット内部) A.getName(request.getParameter("name")); ◆サンプルメソッド public class A { public static String getName(String name) { return name + "さん"; } } おわかりになる方、おられましたら ご教授戴けると助かります。 よろしくお願い致します。 | ||||||||
|
投稿日時: 2006-07-11 15:27
うーん?
共有されるのはメソッドであって、引数や戻り値ではないですが。 | ||||||||
|
投稿日時: 2006-07-11 15:27
この場合、スレッド間で共有するリソースが一切ありませんので、そういった問題は発生しません。メソッドのパラメータやローカル変数は、スレッド毎に独立したものです。
たとえば、次のようになると、s_name がスレッド間で共有されるので問題になります。
| ||||||||
|
投稿日時: 2006-07-11 16:57
ご回答ありがとうございます。
メソッドの引数や、戻り値に関しては メモリ上の別な位置に確保されるのでしょうか。 その辺の切り分けが、ややこしくて混乱していました。 ただ、ご回答いただいた内容を見てなるほどとも思いました。 実際staticなメソッドは色々なクラスでも使われている様ですが 最終的には、クラス変数の定義にさえ気を付ければ競合等の問題は無いと いうことでよろしいでしょうか。 | ||||||||
|
投稿日時: 2006-07-11 17:47
スタックやメモリ管理をキーにして検索すると、役に立つページが
見つかるかもしれません。とりあえず見つかったページを挙げておきます。 http://www.h6.dion.ne.jp/~junpei/memoryAndPointer.html Cを中心に述べていますが、Javaでも同様です。 このあたりのことは言語に寄らず共通する知識ですので、 プログラマなら必ず知ってて欲しいですね。 | ||||||||
|
投稿日時: 2006-07-12 22:29
同じ参照を複数のスレッドで同時に利用すれば問題アリですね。 「同じ参照を同時に利用する」のパターンとしては 1.staticフィールドを参照する場合 2.同一インスタンスのフィールドを参照する場合 ですかね。 1.のstaticフィールドですが、 露骨にHoge.piyo = 47;みたいに更新する場合はともかく、 staticメソッド内などで更新する場合なども該当するので そういうケースでは適切に同期をとらなくてはなりません。 2.の同一のインスタンスの場合はpublicな インスタンスフィールドを作成しなければ、 そのクラス内部で同期処理を完結させればいいので まだ比較的楽なほうでしょうか。 Servletにインスタンスフィールドを作った場合などは 2に該当して同時アクセスでバグが起きることなどがあります。 いずれにせよ、フィールドにする必要がない変数は 極力スコープを狭くするようにしておけば大丈夫です。 ローカル変数であれば通常は同期を気にすることはありません。 このあたりについて理解を深めたければ http://www.hyuki.com/dp/dp2.html 「Java言語で学ぶデザインパターン入門マルチスレッド編」が お勧めです。デザインパターンの本ではあるのですが、 同期関連についても丁寧に解説してあるのでわかりやすいのではないでしょうか。 | ||||||||
|
投稿日時: 2006-07-13 09:34
ローカル変数やメソッドの引数などスタックに保持されるデータはスレッドそれぞれで管理されるため、競合しません。
そのとおりです。 | ||||||||
|
投稿日時: 2006-07-13 12:45
スタック上に実体のあるもの(プリミティブ型)は確実に競合しませんが、 オブジェクトの場合は確実に競合しないのは参照元だけですよ。 参照先が競合するかどうかはプログラム次第です。
そんなことありません。 staticは何も考えなくても複数のスレッドから同時にアクセスできるため 競合が発生しやすいのですが、非staticでもプログラムの作り次第で 複数スレッドから共有されることは普通にあるでしょう。 短絡的に「これはこう」って憶えるのは危なっかしい感じがします。 |