- PR -

ローカル変数は、絶対に共有されない・・・?

投稿者投稿内容
金星太郎
会議室デビュー日: 2002/12/12
投稿数: 7
お住まい・勤務地: 新潟市
投稿日時: 2003-06-05 16:38
みなさま、こんにちは。Asp.NetでWebアプリケーションの開発を行っております。

 以前、あるスレッドで、Moduleの中で宣言されたPublic変数、Private変数は
セッション間で共有されると書かれており、テストしてみました。
(申し訳ないですが、どのスレッドかは忘れ、かつ探し出せませんでした)

 テストした結果、共有されました。
ローカル変数は、共有はされませんでした。

それが、今になってローカル変数は本当に共有されないのか、
確信が持てなくなりました。その時のテストは、ボタンをクリックしたら、
Moduleの中のPublicな関数を実行し、その関数の中のループでローカル変数に加算を行い、
その結果を返す処理でした。結果、ループの中のローカル変数は複数のセッション間で
共有されませんでした。

 でも、今にして思うと、どんなに多くのセッションを同時に立ち上げても、
CPUが一個だったら、割り込みが発生しないのではないか・・・と不安になり、
2個CPUがあるサーバーで、以下の関数の結果を、4個のセッションを同時に
実行して試しました。

Module Module1
Public Function Test5() As Long
Dim S As Long
Dim V As Long

S = 0
S = 1 : V += S : System.Threading.Thread.Sleep(10)
S = 2 : V += S : System.Threading.Thread.Sleep(10)
              ・
              ・
(21844行、上記の行が続く)

Test5 = V
End Function
End Module

Thread.Sleepは、Windows版のDoEvnetsみたいに処理をあけわたしてくれるもの・・・?と
考えてつけました。テストの結果はOKでした。でも確信がありません。
CPUとセッションの数が多ければ、上の関数の変数SとVは共有されて、
結果は正しくないのでは・・・?
それとも、スリープする時間が短いのでは・・・?
と不安です。

そもそも、確信が持てない理由は、3点あります。
 ・なぜ、Private変数が共有されるのかわからないです。
  アプリケーション変数は、何のためにあるのしょうか?
 ・スレッドとプロセスの違いが明確にわからないです。
  スレッドはプロセスの中で、実行を止めたり、再開できるプロセスの中の
  処理単位らしい・・・というのは、わかりましたが、
  どうして、変数を共有してくれるのかわからないです。
 ・どうして、セッションはスレッド単位なのでしょう?
  過負荷攻撃にさらされた時、スレッド単位だと対処の方法が無いのでは・・・?
  プロセスならば何とかできるとは思えないけど、少なくともタスクマネージャーで
  どんな状況か確認できます。


考えるに、テストでは解決しないと気づきました。
そして、マニュアルを読んでも、わからず聞くことにしました。


後、もう一つ気のなることがあります。
複数のセッションで同時に実行すると正しい結果を返さない関数や
ステートメントがあるのでは・・・という事です。
例えば、マイクロソフトがその関数を実現するのに、Moduleの中のPrivate変数を
使っていれば、当然、正しい結果を返しません。


勉強不足からくる、単なる杞憂かもしれませんが、回答をお待ちしています。

_________________
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-06-09 13:12
こんにちは。

 書いてある内容がちょっと理解しにくいのですが…

 ローカル変数が「関数内で宣言された変数」という意味であれば、『絶対に』とは言い切れませんが(つまり、バグがないとはいえない)、共有されません。そういう仕様です。ただし、関数内にSTATIC宣言した場合は別です。これはメモリが共有されるので、他のスレッドなどで『共有』と言うより、使い回しされます。

 この辺、アセンブラorコンパイラの動きを知っていればわかることですが・・・
 ハイパースレッディングだろうと、マルチCPUだろうと、プログラム自身が扱えるメモリ領域のどこを、どの関数のローカル変数として割り当てるかはプログラム自身が管理しているので、プログラム自身、つまり使っているライブラリのメモリ管理機構にバグがあるとか、STATIC宣言などの『共有』することを示す宣言をしない限り、共有はされません。
 他の関数にジャンプするとき、関数内で宣言された変数は、スタックに待避されます。このとき、スタックの取り出しについてバグがあれば、『共有する』というより、横取りされてしまいます。そして、どこかの段階で取り出すべき変数がなくなってアボートするしかなくなります。

 「こういう状況下では共有されます。こういう状況では共有されません」と、一定しなければ怖くてプログラムできないと思いますが??


(それとも、Z80(ゼッパチ)の頃の知識なので、今は違うのか?)
金星太郎
会議室デビュー日: 2002/12/12
投稿数: 7
お住まい・勤務地: 新潟市
投稿日時: 2003-06-10 10:14
Jitaさん、レスありがとうございます。

> 他の関数にジャンプするとき、関数内で宣言された変数は、スタックに待避されます。
>このとき、スタックの取り出しについてバグがあれば、『共有する』というより、横取り
>されてしまいます。そして、どこかの段階で取り出すべき変数がなくなってアボートする
>しかなくなります。
逆にいうと、Moduleの中に宣言されたPublic変数やPrivate変数は、
スタックの中に退避されないから、『共有』もしくは、横取りされるかもしれないと言う
ことでしょうか・・・?


> 「こういう状況下では共有されます。こういう状況では共有されません」と、一定しなければ怖く
>てプログラムできないと思いますが??
Asp.Netの場合、Moduleの中のPublicな関数の中のLocal変数なら共有されるけど、
ClassのMethodの中のLocal変数は共有されません・・・と私の知らない暗黙の一定(常識)でも
あるのだろうかと思っていました。
また、Classは、Instanceを作って利用するという手順から『共有』されることは、
絶対にないと思っています。もし、『共有』させるなら、Instanceを作るという手間は
不要だからです。

Jitaさんにお聞きします。
 Asp.Netの場合、Moduleの中のPublic変数、Private変数は共有される
というのは、不思議に思えませんか・・・?特に、Private変数がです。
私は、別のプログラミングをしている人に聞きましたが、とても、不思議がっていました。
そして、考えました。
すると、その不思議はLocal変数までにも及ぶのではないかと不安になったのです。
小野@どっとねっとふぁん
ぬし
会議室デビュー日: 2001/10/30
投稿数: 402
投稿日時: 2003-06-10 10:50
Moduleというものが特殊なんだと考えたほうがいいかと。。。
C#でいえば、メンバーのすべてがstaticとして定義されているものがModuleと同等に
なるらしいです。
VBが持っていたModuleを.NET Framework上で実現するために、現時点ではそのような
実装になっているというようなお話でした。

#互換性のために無理してる、と。。。(^^;
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-06-10 18:24
引用:

V2000sv01さんの書き込み (2003-06-10 10:14) より:

Jitaさんにお聞きします。
 Asp.Netの場合、Moduleの中のPublic変数、Private変数は共有される
というのは、不思議に思えませんか・・・?特に、Private変数がです。
私は、別のプログラミングをしている人に聞きましたが、とても、不思議がっていました。
そして、考えました。
すると、その不思議はLocal変数までにも及ぶのではないかと不安になったのです。


 とりあえず、私だと思うので(私はJitaじゃなくて、Jitta(じった)なのよぉ〜)

 まず、ASP.NETとVB.NETを混同しないでください。MODULE定義ができるのはVisualBasicで、ASPではありません。そして、小野@EACさんのおっしゃるように、MODULE定義が特殊なのです。これは過去のバージョンのMODULEとの下位互換のためにあります。EXCELやWORDのマクロであるVBA、何の略かご存じですか?VisualBasic for Applicationです。VBはマクロとしても利用できるように設計されていたのです。VBScriptというのもありますね。こういったものと互換をとるためにあるのです。従って、上位バージョンで追加されたPRIVATE宣言は、MODULE宣言ができた当時にはなかった(と思う)ので無効となる、と考えてよいのではないでしょうか。
金星太郎
会議室デビュー日: 2002/12/12
投稿数: 7
お住まい・勤務地: 新潟市
投稿日時: 2003-06-11 11:01
小野@EACさん、Jittaさん、レスありがとうございます。
Jittaさん、名前間違えていました。すみません。

私は、Moduleという時、モジュールブロック(or モジュールステートメント)の事を
示していたつもりでした。言葉が曖昧で、悪かったと思っています。
レスで出てくるModule定義、Module, Module宣言は

Module定義 = モジュールブロックの中のプロシージャー or 関数
Module = モジュールブロックの中のプロシージャー or 関数
Module宣言 = モジュールブロック

と考えたけど、多分、あっていると思います。


私なりにまとめてみました。
.Net Frameworkでは、Asp.Netにおいて、VBのような記述を許しているが、
VB.Netを提供しているのでなく、Asp.Netでできることを、
VBライクにコーディングできるようにしている。
そのため、以下の2点は、特別もしくは無効になっている。

 1.モジュールブロックの中のプロシージャー or 関数
  ClassのStaticなMemberと同等になる。
 2.モジュールブロックの中のPrivate宣言
  複数のセッション間で、共有される。

そもそもAsp.Netでは、モジュールは使えない。


そうすると、私の最初の問題点であった”Module(モジュールブロック)の中の
Public関数の中のLocal変数は絶対に共有されない?”という疑問は
"No"なんですね。
Asp.Netは、VB.Netでないのだから、モジュールを使うべきでなく、
モジュールを使った場合、その中のLocal変数の値が
共有されない事は保証されない。

もしかして、Asp.Netって、クラスステートメントの使用も
認めていないのでは・・・・という気がします。なぜって、Session変数を
用いなくても、クラスの中でスタティックな変数を宣言すればよいからです。
(本当に、Session変数の変わりになるのか試したことはないですが・・・)

そうすると、各画面で共通関数を用意したいときは、WebServiceという事に
なってしまうのでしょうか・・・?

小野@どっとねっとふぁん
ぬし
会議室デビュー日: 2001/10/30
投稿数: 402
投稿日時: 2003-06-11 13:37
あーあ、完全に勘違いされてしまっている。
Jittaさんの言葉の使い方に不正確なところがあるせいかと思うけど。。。

ASP.NETで利用するのはVB.NETです。もしくはC#とかJScript.NETです。
VB.NETに似た別のなにかが提供されているわけではありません。

で、ModuleはVBからアップグレードしてくる人が使いやすいように
VB.NETにおいて提供されている機能なのですが、ASP.NETで利用する
場合は注意が必要な機能になってしまっています。
これは、ASP.NETが「サービス」として動くアプリケーション
(Webアプリケーション)で、ちょっと特殊であるせいです。
きちんとわかってて使うならいいんですけど、できればASP.NETの
中ではModuleを利用しないほうがはまる可能性が低くなるでしょう、
と私はいいたかったんです。

ASP.NETの中でのクラスの利用ですが、当然できます。
つか、それが使えなかったらコードビハインドでの記述ができません。
で、ASP.NETでC#でいうstaticな変数を使うと、Sessionじゃなく
Applicationオブジェクトと同じような動きになります。
このあたりがきっちり理解できてないと、はまるだろうな、と
私が思う点であったりします。

まぁ、ASP.NETがどのような仕組みで動いてるか、という
ところがわかってくればなんとなくわかるところでは
あるのですが、それまではModuleとかstaticとかは
使わず、SessionオブジェクトとかApplicationオブジェクトを
利用していくほうがいいでしょう。
そのためにわざわざ用意してくれているんですしね。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-06-11 13:46
引用:

小野@EACさんの書き込み (2003-06-11 13:37) より:
Jittaさんの言葉の使い方に不正確なところがあるせいかと思うけど。。。


間違って理解しているわけですね。どの辺でしょう?

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