- PR -

サーブレットにおけるprivateなインスタンス変数について

投稿者投稿内容
長州人
会議室デビュー日: 2005/02/06
投稿数: 5
お住まい・勤務地: 東京
投稿日時: 2005-02-06 22:09
サーブレットはマルチスレッドで動作するので、
インスタンスは、各スレッドで共有されることになりますが、
サーブレットとビジネスロジック間に以下のようなValueObjectを使っているとして、
 
 public class ValueObject1 {
  private String name = "";
 
  public String getName(){
  return name;
  }

  public String setName(String param){
  name = param;
  }
 }

このValueObject1のインスタンス変数nameは、スレッドセーフと言えるのでしょうか?

スレッドに共有されてるサーブレットからインスタンス化されたValueObject1は、
当然、スレッドからも使い回しされると思うので、
スレッドAが、ValueObject1.setName("山田")として、privateなnameにデータを保持した場合、
スレッドBが、ValueObject1.setName("藤本")として、privateなnameにデータを上書きした場合、
スレッドAで、ValueObject1.getNameとした場合、藤本とデータが取得できるような気がするのですが。
YOU@IT
ぬし
会議室デビュー日: 2002/03/29
投稿数: 284
お住まい・勤務地: 大阪
投稿日時: 2005-02-06 23:32
そのValueObject1のインスタンスが、サーブレットからどのように
参照されているかによります。

つまり、ValueObject1のインスタンスが、
 ・サーブレットのインスタンスフィールドで参照される場合は、複数のスレッド間の競合が起こります。
 ・サーブレットのメソッドローカル変数で参照される場合は、競合は起こりません。
のようになります。

長州人
会議室デビュー日: 2005/02/06
投稿数: 5
お住まい・勤務地: 東京
投稿日時: 2005-02-07 10:54
回答有難うございました。

>・サーブレットのインスタンスフィールドで参照される場合は、
> 複数のスレッド間の競合が起こります。
>・サーブレットのメソッドローカル変数で参照される場合は、競合は起こりません。

ということは、ValueObject1のnameフィールドがpublicでも、
ローカル変数から参照されているときは、競合は起こらないと言えるのですよね?

色々な参考書を見るとpublicな変数は書換えが起こる場合があるので、
使わないようにとありますが、
これは、多人数で開発しているときに、他人によって変更される恐れがあるため、
『publicな変数は使わないように』ということを意味してるということでしょうか。
ローカル変数で参照してる限りpublicな変数であっても、
スレッドによる競合は起こらないという認識で宜しいでしょうか?


# 初心者の質問で申し訳ないです・・・・
tak3
ベテラン
会議室デビュー日: 2004/04/15
投稿数: 80
お住まい・勤務地: 菜の花・銀杏
投稿日時: 2005-02-07 11:24
一度、スレッドとか可視性とか変数の種類についての知識を整理することをオススメします。

>>・サーブレットのインスタンスフィールドで参照される場合は、
>> 複数のスレッド間の競合が起こります。
>>・サーブレットのメソッドローカル変数で参照される場合は、競合は起こりません。

>ということは、ValueObject1のnameフィールドがpublicでも、
>ローカル変数から参照されているときは、競合は起こらないと言えるのですよね?

YES
「可視性」と「変数が複数スレッドで共有される」かは別の話です

>色々な参考書を見るとpublicな変数は書換えが起こる場合があるので、
>使わないようにとありますが、
>これは、多人数で開発しているときに、他人によって変更される恐れがあるため、
>『publicな変数は使わないように』ということを意味してるということでしょうか。

NO
他人でなくても自分でも「変更に対する防御ができないのがpublicな可視性」です
たとえば、負数の設定が不可な変数を用意する場合、publicなインスタンス変数は、
直接、負数が設定できてしまう危険性があります。
気をつけてコーディングすればいいという話でもありますが、
アクセッサーで入力チェック(負数を例外にする、0に丸める等)を行う方が安全です。

>ローカル変数で参照してる限りpublicな変数であっても、
>スレッドによる競合は起こらないという認識で宜しいでしょうか?

YES
複数のスレッドで共有される変数は、サーブレットのインスタンス変数です。
(くどいですが、privateとかpublicとか関係ないです<サーブレットのインスタンス変数)
ローカル変数が云々というよりは、メソッド内でインスタンス変数を操作してるかが
ポイントになります。

[ メッセージ編集済み 編集者: tak3 編集日時 2005-02-07 11:27 ]
長州人
会議室デビュー日: 2005/02/06
投稿数: 5
お住まい・勤務地: 東京
投稿日時: 2005-02-09 20:18
YOU@IT様、TAKE3様>
ご回答有難うございました。
大変良く分かりました。
パテ太
ベテラン
会議室デビュー日: 2004/08/16
投稿数: 64
お住まい・勤務地: 千葉・東京
投稿日時: 2005-02-09 22:11
パテ太と申します。
一応話は終わっているようですが・・・

ValueObject1については
1.getNameメソッドはフィールドnameの値を返す
 単一の処理を行っている。
 Stringは変更できないためこの処理は安全である。
2.setNameメソッドはStringの参照値の代入のみの
 単一の処理を行っている。
 これもStringは変更できないため安全である。

よってスレッドセーフである。

で良いような気がしますがどうでしょう?
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2005-02-10 02:18
setName で変数 name がスレッドセーフかどうかは ValueObject1 がスレッド間で共有されるかどうかによりますね。
感覚がつかめないときは JMeter などで負荷をかけてみて実際に競合状態を作り出してみると良いですよ。
#タイミングによってはうまく再現させられないこともありますが・・・・
競合状態で変数が共有されておかしな挙動が発生する状態で synchronized メソッドやブロックを作ったり、インスタンスを共有しないように書き直したりなどして現象が収まればイメージしやすくなると思います。
パテ太
ベテラン
会議室デビュー日: 2004/08/16
投稿数: 64
お住まい・勤務地: 千葉・東京
投稿日時: 2005-02-10 09:12
引用:

インギさんの書き込み (2005-02-10 02:18) より:

競合状態で変数が共有されておかしな挙動が発生する状態で synchronized メソッドやブロックを作ったり、インスタンスを共有しないように書き直したりなどして現象が収まればイメージしやすくなると思います。



パテ太です。
ValueObject1 の SetName は
参照の代入のみのアトミックな処理に見えますが
違うのでしょうか?

アトミックな処理に Synchronized は必要ないし
競合は起こりえないと思うのですが・・・。

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