質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.04%

Struts1.xを使用したスレッドセーフについて

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 2,781

syncrock

score 198

Struts1.xではActionは1つしかインスタンス生成してくれないので、スレッドセーフにするために何かしら対策を行う必要があると思います。
ネットで調べると、例えばSpringなどのDIコンテナを使うとか。
Springでscopeをprototypeにしておくと、インスタンスをリクエストごとに作成してくれるそうですが。

例えば、以下のようなコードがあるとします。
public class ActionForm {
    private String a = null;
    public String getA() {
        return this.A;
    }
    public String setA(String argA) {
        this.A = argA;
}
このクラスを以下のような形で使用した場合。
public class TestAction extends EventDispatchAction {
    protected ActionForward dispatchMethod(省略){
        ActionForm form= new ActionForm ();
        //何かしらの継続処理
    }
}
スタック領域にはformという参照型変数ができ、ヒープ領域にActionFormが格納されると思っています。(ここが間違えていたらすいません)
そこで気になるのは、インスタンスがスレッド別に出来ていたとしてもマルチスレッドであれば、ヒープ領域にある時点でデータの書き換えが起こり得ることになりませんか?
すなわち、スレッドセーフではなくなるのではないかと思っています。
それとも、呼び出し元のアクションがスレッド別にインスタンスが生成されていれば、ヒープ領域に格納されていたとしても問題ないのでしょうか。
もしそうであれば、生成された1つのアクションからスレッド毎にメイン処理が書かれているクラスをインスタンス生成して、その中でフィールド定義などのヒープ領域に格納される変数が存在しても問題ない、スレッドセーフであるのでしょうか。
(コードに不備があっても目を瞑っていただければ。質問の意図さえ伝わればと思います。)
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

TestActionのdispatchMethodの中にあるformは、そのメソッドの実行中にのみ存在するオブジェクトですから(わざとメソッドの外に渡さなければ)、他のスレッドによる影響を受けることはありません。

マルチスレッドの問題を考える必要が出てくるのは、TestActionのインスタンス変数およびActionFormのクラス変数(staticメンバ)です。ここでは、どちらもありませんから、スレッドセーフは脅かされていません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/04/23 16:38

    スレッド毎に別の空間にオブジェクトが作られるのであれば、インスタンス変数もスレッド毎に別の空間に作られないのでしょうか。
    それともインスタンス変数は1つしか生成されず、スレッドが異なってもそのクラスを扱うスレッドは全て共有するのでしょうか。

    キャンセル

  • 2015/04/23 22:40

    TestAction のインスタンスは、アプリケーションサーバ(たとえばTomcat)において1つだけインスタンス化されて、各スレッドで使い回されます。つまり共有されています。

    しかし、そのdispatchMethodメソッドにおいてnewされるActionFormのインスタンスは、HTTPリクエスト毎に作られるスレッド毎にヒープ上の未使用の領域に作られますので、共有されません。わかりますか?

    キャンセル

  • 2015/04/23 22:52

    わかりました、ありがとうございます。
    理解に欠けてた私に何レスもありがとうございます!

    キャンセル

0

インスタンスがスレッド別に出来ていたとしてもマルチスレッドであれば、
ヒープ領域にある時点でデータの書き換えが起こり得ることになりませんか? 

少なくともこのActionFormに限って言えば、スレッドごとにヒープの 異なる領域 にインスタンスが生成されます。なので、わざと他のスレッドにインスタンスを渡したりしなければ、理論上はデータの書き換えは起こり得ません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/04/23 19:06

    ということは、スレッド毎に作られたインスタンス内で、インスタンス変数が作られるようなロジックがある場合、その作られたインスタンス変数は他のスレッドでも触られることがあり得なくはないということですか?

    キャンセル

  • 2015/04/23 20:35

    takenori.soneさんのご回答にあるように、スレッド毎に作られたインスタンスをクラスフィールド(staticなフィールド)に置かなければ、他のスレッドで触られることはありません。
    つまり、前述の「共有するかしないかをプログラムする側で選択する」の部分は、クラスフィールドにインスタンスを格納する(=共有する)かしないか、という意味です。

    キャンセル

  • 2015/04/23 22:52

    ありがとうございます、やっと理解出来ました。

    キャンセル

0

ということは、スレッド毎に作られたインスタンス内で、インスタンス変数が作られるようなロジックがある場合、その作られたインスタンス変数は他のスレッドでも触られることがあり得なくはないということですか?

スレッドの中で new で作ったオブジェクトは基本的には、そのスレッドのものです。
またメソッドを呼び出した際に生成する引数やローカル変数(メソッドを呼び出す度にメモリー上に生成します。)も呼び出したスレッドのものです。
ローカル変数や引数そのものは他のスレッドとどうあっても共有できません。
一方、new で作ったオブジェクトは共有する仕組みをプログラマが明示的に作れば共有できます。

他のスレッドと変数を共有するにはどうすれば良いか、というとクラスのstaticなメンバー変数を使う必要があります。
staticなメンバー変数にオブジェクトを持たせると、そのオブジェクトをJVM全体で共有することができます。
つまり複数のスレッドで同じオブジェクトを共有できます。

言い換えると、static なメンバ変数に new で作成したオブジェクトを持たせない限りは他のスレッドから、そのオブジェクトにアクセスすることはできません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/04/23 22:52

    回答有難うございました。
    理解出来ました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる