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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

Struts

StrutsはJava向けのWebアプリケーションフレームです。MVCモデルに基づいており、JSPやJavaサーブレットを組み合わせ、アプリケーション構築時に使用する各機能を提供しています。

Q&A

解決済

3回答

6463閲覧

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

syncrock

総合スコア209

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

Struts

StrutsはJava向けのWebアプリケーションフレームです。MVCモデルに基づいており、JSPやJavaサーブレットを組み合わせ、アプリケーション構築時に使用する各機能を提供しています。

0グッド

0クリップ

投稿2015/04/23 05:12

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

例えば、以下のようなコードがあるとします。

lang

1public class ActionForm { 2 private String a = null; 3 public String getA() { 4 return this.A; 5 } 6 public String setA(String argA) { 7 this.A = argA; 8}

このクラスを以下のような形で使用した場合。

lang

1public class TestAction extends EventDispatchAction { 2 protected ActionForward dispatchMethod(省略){ 3 ActionForm form= new ActionForm (); 4 //何かしらの継続処理 5 } 6}

スタック領域にはformという参照型変数ができ、ヒープ領域にActionFormが格納されると思っています。(ここが間違えていたらすいません)
そこで気になるのは、インスタンスがスレッド別に出来ていたとしてもマルチスレッドであれば、ヒープ領域にある時点でデータの書き換えが起こり得ることになりませんか?
すなわち、スレッドセーフではなくなるのではないかと思っています。
それとも、呼び出し元のアクションがスレッド別にインスタンスが生成されていれば、ヒープ領域に格納されていたとしても問題ないのでしょうか。
もしそうであれば、生成された1つのアクションからスレッド毎にメイン処理が書かれているクラスをインスタンス生成して、その中でフィールド定義などのヒープ領域に格納される変数が存在しても問題ない、スレッドセーフであるのでしょうか。
(コードに不備があっても目を瞑っていただければ。質問の意図さえ伝わればと思います。)

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

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

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

投稿2015/04/23 05:20

chokojori

総合スコア971

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

syncrock

2015/04/23 05:33

回答ありがとうございます。 >そのメソッドの実行中にのみ存在するオブジェクトですから 質問にも書いてますが、newされたインスタンスはヒープに格納されると思っていますのが、TestActionが複数スレッドで実行されてもスレッドセーフは脅かされないというのは、ローカル変数であればヒープに格納されたところで共有されないのでしょうか。 イメージとしては、「このメソッドのものはここに格納してね」というヒープの中に部屋がわかれているのでしょうか。
chokojori

2015/04/23 06:00

メソッド呼び出しの単位でヒープに作られ、そのヒープに作られたオブジェクトは、別のタイミングのメソッド呼び出しからは参照されません。
chokojori

2015/04/23 06:01

つまり、メソッドを定義したときにこのオブジェクトがヒープに確保されるのではなく、メソッドの「実行時」にオブジェクトがヒープに確保されるのです。
syncrock

2015/04/23 06:06

ということは、複数のスレッドで動いており、オブジェクトが作られるタイミングが同じことがあるとすれば、スレッドセーフは脅かされることもあるということですか? すごい稀な確率であり得るかどうかは別ですが。
chokojori

2015/04/23 06:11

ちがいます。スレッドごとに別の空間です。ヒープ上にオブジェクトを確保するとき、未使用の領域を必ず使います。スレッド1でnewするときのオブジェクトと、スレッド2でnewするときのオブジェクトは、それぞれ未使用の領域をヒープから確保しますので、必ず別のオブジェクトになります。
syncrock

2015/04/23 07:38

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

2015/04/23 13:40

TestAction のインスタンスは、アプリケーションサーバ(たとえばTomcat)において1つだけインスタンス化されて、各スレッドで使い回されます。つまり共有されています。 しかし、そのdispatchMethodメソッドにおいてnewされるActionFormのインスタンスは、HTTPリクエスト毎に作られるスレッド毎にヒープ上の未使用の領域に作られますので、共有されません。わかりますか?
syncrock

2015/04/23 13:52

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

0

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

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

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

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

投稿2015/04/23 10:51

takenori.sone

総合スコア11

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

syncrock

2015/04/23 13:52

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

0

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

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

投稿2015/04/23 05:31

argius

総合スコア9390

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

syncrock

2015/04/23 05:37

回答ありがとうございます。 ヒープの中で「共有される領域」と「共有されない領域」があるのでしょうか。 それとも、インスタンスが生成されるクラスがスレッド毎に作成されていれば、ヒープの中のそれぞれのスレッドだけが使用する領域に格納されるのでしょうか。
argius

2015/04/23 06:22

「共有される領域」と「共有されない領域」というのは特にありません。共有するかしないかをプログラムする側で選択します。何もしていないのに共有されているとしたら、見えないところで誰かが共有させているはずです。 また、特にそのスレッドだけが使用する領域があるわけではありません。単にnewするたびに新しい空き領域にそのインスタンスがつくられるだけです。
syncrock

2015/04/23 10:06

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

2015/04/23 11:35

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

2015/04/23 13:52

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問