- PR -

Javaのクラスメソッド(static)について

投稿者投稿内容
カズリー
会議室デビュー日: 2006/07/11
投稿数: 3
投稿日時: 2006-07-11 15:13
はじめまして。
いつも参考にさせて戴いております。

Javaのクラスメソッドに関してお聞きしたいのですが
サーブレットの様な、不特定多数のアクセスを受け付けるアプリケーションを
作成する場合に、例えば名前に一律「さん」等の文字を付けるメソッドを
クラスメソッドとして実装した場合には、クラスメソッドの特性からすると
一つのメソッドを、あらゆるオブジェクトと共有すると言うことなので
場合によっては
(ロードアベレージ等で負荷がかかっている場合は処理の遅延等が発生し)
データの競合(別なスレッドで登録した名前が表示されてしまう)が発生
するのでは無いかと懸念しておりますが、私の理解は間違えているでしょうか。

※サーブレットで受け取ったリクエストを、サーブレット内部で下記の
 メソッドを実装したクラスを利用するイメージです。

◆呼び出し側(サーブレット内部)
A.getName(request.getParameter("name"));

◆サンプルメソッド
public class A {
public static String getName(String name) {
return name + "さん";
}
}

おわかりになる方、おられましたら
ご教授戴けると助かります。

よろしくお願い致します。
mio
ぬし
会議室デビュー日: 2005/08/25
投稿数: 734
お住まい・勤務地: 神奈川県
投稿日時: 2006-07-11 15:27
うーん?
共有されるのはメソッドであって、引数や戻り値ではないですが。
スフレ
ぬし
会議室デビュー日: 2005/05/27
投稿数: 281
お住まい・勤務地: 東京
投稿日時: 2006-07-11 15:27
この場合、スレッド間で共有するリソースが一切ありませんので、そういった問題は発生しません。メソッドのパラメータやローカル変数は、スレッド毎に独立したものです。

たとえば、次のようになると、s_name がスレッド間で共有されるので問題になります。
コード:
public class A {
  private static String s_name;
  public static String getName(String name) {
    s_name = name;
    return s_name + "さん";
  }
}


カズリー
会議室デビュー日: 2006/07/11
投稿数: 3
投稿日時: 2006-07-11 16:57
ご回答ありがとうございます。

メソッドの引数や、戻り値に関しては
メモリ上の別な位置に確保されるのでしょうか。

その辺の切り分けが、ややこしくて混乱していました。

ただ、ご回答いただいた内容を見てなるほどとも思いました。

実際staticなメソッドは色々なクラスでも使われている様ですが
最終的には、クラス変数の定義にさえ気を付ければ競合等の問題は無いと
いうことでよろしいでしょうか。


koe
大ベテラン
会議室デビュー日: 2003/07/13
投稿数: 198
投稿日時: 2006-07-11 17:47
スタックやメモリ管理をキーにして検索すると、役に立つページが
見つかるかもしれません。とりあえず見つかったページを挙げておきます。

http://www.h6.dion.ne.jp/~junpei/memoryAndPointer.html

Cを中心に述べていますが、Javaでも同様です。
このあたりのことは言語に寄らず共通する知識ですので、
プログラマなら必ず知ってて欲しいですね。
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2006-07-12 22:29
引用:

実際staticなメソッドは色々なクラスでも使われている様ですが
最終的には、クラス変数の定義にさえ気を付ければ競合等の問題は無いと
いうことでよろしいでしょうか。



同じ参照を複数のスレッドで同時に利用すれば問題アリですね。
「同じ参照を同時に利用する」のパターンとしては

1.staticフィールドを参照する場合
2.同一インスタンスのフィールドを参照する場合

ですかね。
1.のstaticフィールドですが、
露骨にHoge.piyo = 47;みたいに更新する場合はともかく、
staticメソッド内などで更新する場合なども該当するので
そういうケースでは適切に同期をとらなくてはなりません。

2.の同一のインスタンスの場合はpublicな
インスタンスフィールドを作成しなければ、
そのクラス内部で同期処理を完結させればいいので
まだ比較的楽なほうでしょうか。

Servletにインスタンスフィールドを作った場合などは
2に該当して同時アクセスでバグが起きることなどがあります。

いずれにせよ、フィールドにする必要がない変数は
極力スコープを狭くするようにしておけば大丈夫です。
ローカル変数であれば通常は同期を気にすることはありません。

このあたりについて理解を深めたければ
http://www.hyuki.com/dp/dp2.html
「Java言語で学ぶデザインパターン入門マルチスレッド編」が
お勧めです。デザインパターンの本ではあるのですが、
同期関連についても丁寧に解説してあるのでわかりやすいのではないでしょうか。
Anthyhime
ぬし
会議室デビュー日: 2002/09/10
投稿数: 437
投稿日時: 2006-07-13 09:34
引用:

メソッドの引数や、戻り値に関しては
メモリ上の別な位置に確保されるのでしょうか。


ローカル変数やメソッドの引数などスタックに保持されるデータはスレッドそれぞれで管理されるため、競合しません。
引用:

実際staticなメソッドは色々なクラスでも使われている様ですが
最終的には、クラス変数の定義にさえ気を付ければ競合等の問題は無いと
いうことでよろしいでしょうか。


そのとおりです。
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2006-07-13 12:45
引用:

Anthyhimeさんの書き込み (2006-07-13 09:34) より:
ローカル変数やメソッドの引数などスタックに保持されるデータはスレッドそれぞれで管理されるため、競合しません。


スタック上に実体のあるもの(プリミティブ型)は確実に競合しませんが、
オブジェクトの場合は確実に競合しないのは参照元だけですよ。
参照先が競合するかどうかはプログラム次第です。

引用:

そのとおりです。


そんなことありません。

staticは何も考えなくても複数のスレッドから同時にアクセスできるため
競合が発生しやすいのですが、非staticでもプログラムの作り次第で
複数スレッドから共有されることは普通にあるでしょう。

短絡的に「これはこう」って憶えるのは危なっかしい感じがします。

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