<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>スレッドとオブジェクトインスタンス</title><link>http://blogs.msdn.com/nakama/archive/2008/12/18/9231090.aspx</link><description>さてさて、この blog、基本的には玄人向けに濃い話題ばっかり書いていたのですが、実は最近、新人さんの方々にも割と読んでいただいていることが判明。ちょ、さすがにぜんぜん意味不明なエントリが多いのでは？？ とか思ったりするのですが、そんな感じだとたまには割と入門者向けのエントリも書いてみたくなります。そんなわけで、今日はたまには基本に立ち返って、スレッドとオブジェクトインスタンスの話題を書いてみます。このネタを取り上げようと思ったのは、ある人からの質問メール。（ちょっと微修正しましたが^^） 「最近、3</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>re: スレッドとオブジェクトインスタンス</title><link>http://blogs.msdn.com/nakama/archive/2008/12/18/9231090.aspx#9250136</link><pubDate>Tue, 23 Dec 2008 17:44:55 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9250136</guid><dc:creator>kazenami</dc:creator><description>&lt;p&gt;ふぁ～&lt;/p&gt;
&lt;p&gt;nakamaｻﾝ、いささか全力過ぎやしませんでしょうか（＋＿＋）&lt;/p&gt;
&lt;p&gt;・・・&lt;/p&gt;
&lt;p&gt;（嘘です。疑問がに思っていたことが、限りなくクリアに、理解されかかってきました。。）&lt;/p&gt;
&lt;p&gt;と、いう冗談はさておき、&lt;/p&gt;
&lt;p&gt;クイズしてみました！&lt;/p&gt;
&lt;p&gt;私の答えは、&lt;/p&gt;
&lt;p&gt;MethodA:スレッドセーフ&lt;/p&gt;
&lt;p&gt;（ローカル変数c,dはスレッドごとに作成されるため）&lt;/p&gt;
&lt;p&gt;MethodB:&amp;#215;&lt;/p&gt;
&lt;p&gt;（データ変数bを操作する処理を2つ以上のスレッド）&lt;/p&gt;
&lt;p&gt;MethodC:スレッドセーフ&lt;/p&gt;
</description></item><item><title>re: スレッドとオブジェクトインスタンス</title><link>http://blogs.msdn.com/nakama/archive/2008/12/18/9231090.aspx#9250184</link><pubDate>Tue, 23 Dec 2008 18:11:57 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9250184</guid><dc:creator>kazenami</dc:creator><description>&lt;p&gt;まことに申し訳ありません。&lt;/p&gt;
&lt;p&gt;操作を誤り、途中にもかかわらず、Submitしてしまいました。&lt;/p&gt;
&lt;p&gt;ということで、再度書き込みさせていただきます。&lt;/p&gt;
&lt;p&gt;MethodB:&amp;#215;&lt;/p&gt;
&lt;p&gt;（データ変数bを操作する処理を、2つ以上のスレッドが同時に行ってしまうとロストアップデートの可能性があるため）&lt;/p&gt;
&lt;p&gt;MethodC:スレッドセーフ&lt;/p&gt;
&lt;p&gt;（自信がありません）&lt;/p&gt;
&lt;p&gt;↑オブジェクトインスタンスが、どのような条件の時に&lt;/p&gt;
&lt;p&gt;変わるかというのが、分からなかったためです。&lt;/p&gt;
&lt;p&gt;クラスが変わると、オブジェクトインスタンスも変わるのは分かったのですが、スレッドが変わる時は、どうなのかが分かりません。&lt;/p&gt;
&lt;p&gt;例の６個目（？）で、メインスレッドとマニュアルスレッドを使用している際は、スレッドが異なっていても、（同じクラスのため？）&lt;/p&gt;
&lt;p&gt;オブジェクトインスタンスのアドレスは両方とも&amp;amp;Hyyyyになっています。&lt;/p&gt;
&lt;p&gt;しかし、例の７個目では、&lt;/p&gt;
&lt;p&gt;スレッド１のオブジェクトインスタンスのアドレス：&amp;amp;Hxxxx&lt;/p&gt;
&lt;p&gt;スレッド2のオブジェクトインスタンスのアドレス：&amp;amp;Hｙｙｙｙ&lt;/p&gt;
&lt;p&gt;となっています。&lt;/p&gt;
&lt;p&gt;どのような条件で、オブジェクトインスタンスはつくり変わるのでしょうか。&lt;/p&gt;
&lt;p&gt;あまりにもﾄﾝﾁﾝｶﾝな質問でなければ、教えていただけると嬉しいです。&lt;/p&gt;
&lt;p&gt;（長文失礼しました。&lt;/p&gt;
&lt;p&gt;何だか、先程からここのblog荒らしている気がしてならないのですが・・・・、いやしかし、ここは勇気をもってもう一度Submit（`・ω・&amp;#180;））&lt;/p&gt;
</description></item><item><title>re: スレッドとオブジェクトインスタンス</title><link>http://blogs.msdn.com/nakama/archive/2008/12/18/9231090.aspx#9251651</link><pubDate>Wed, 24 Dec 2008 13:08:21 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9251651</guid><dc:creator>HashedBeef</dc:creator><description>&lt;p&gt;はじめまして。&lt;/p&gt;
&lt;p&gt;実は今月のはじめくらいからマルチスレッドについて悩んでおりまして、&lt;/p&gt;
&lt;p&gt;このページを発見したときには目からウロコでした。&lt;/p&gt;
&lt;p&gt;大変参考になりました。&lt;/p&gt;
&lt;p&gt;私も問題を解いてみたのですがまだ理解が足りないみたいで疑問がちらほらでてきました。&lt;/p&gt;
&lt;p&gt;まずMethodAについてです。&lt;/p&gt;
&lt;p&gt;「スレッドセーフなメソッド」のところに書いてある、&lt;/p&gt;
&lt;p&gt;”ローカル変数しか操作していないようなメソッドは、マルチスレッド動作せても問題がない。（※ ローカル変数が参照型で、そのオブジェクトインスタンスを別スレッドからも操作しせてたらダメですが；）” &lt;/p&gt;
&lt;p&gt;という別のスレッドからの操作というのが気になりました。&lt;/p&gt;
&lt;p&gt;ローカル変数が参照型でもスレッドごとに作成した場合はヒープ領域が別々で作られるなら（ここがわかりません）、MethodAもスレッドセーフなのではないかと思います。&lt;/p&gt;
&lt;p&gt;また、MethodCについては、aを使うメソッドが他にないのでスレッドセーフではあると思うのですが、仮にaを使うメソッドがあった場合は値が変わってしまうためスレッドセーフではないのではないかと。&lt;/p&gt;
&lt;p&gt;また、クラスXのインスタンス生成後にマルチスレッドにするのか、スレッドごとにXのインスタンスを生成するかで、スレッドセーフかどうかはわかりませんが互いに干渉するかしないかは変わってくるのではないでしょうか。&lt;/p&gt;
&lt;p&gt;私はスレッドごとに参照型の変数を作成するとヒープ領域が別でとられるのかどうかがわかりません。たぶん別だと思ってますが。&lt;/p&gt;
&lt;p&gt;私も長々と書いてしまいまして申し訳ありませんm( __ __ )m &lt;/p&gt;
&lt;p&gt;ぜひぜひご指導お願いします。&lt;/p&gt;
</description></item><item><title>re: スレッドとオブジェクトインスタンス</title><link>http://blogs.msdn.com/nakama/archive/2008/12/18/9231090.aspx#9252006</link><pubDate>Wed, 24 Dec 2008 20:47:07 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9252006</guid><dc:creator>nakama</dc:creator><description>&lt;p&gt;えと、お二人の質問を元にエントリを立てておきましたので、そちらも参照してください^^。&lt;/p&gt;
&lt;p&gt;&amp;gt; kazenami さん&lt;/p&gt;
&lt;p&gt;こんばんは。クイズの答えですが、MethodA, B については正解。&lt;/p&gt;
&lt;p&gt;問題は MethodC ですが、これはオブジェクトインスタンスがどのように作られているか次第で安全か否かが変わってきます。これは、もう一つのエントリの方を参考にして考えてみてください。&lt;/p&gt;
&lt;p&gt;&amp;gt; HashedBeef さん&lt;/p&gt;
&lt;p&gt;マルチスレッドアプリケーションはなかなか難しいので、ぜひこの機会に勉強してください。&lt;/p&gt;
&lt;p&gt;ちなみに .NET 関係ですと、&amp;quot;Essential .NET&amp;quot; という本が詳しいので、ここのエントリの内容が理解できた上でさらに学習を深めたい場合にはそちらを読んでいただくとよいと思います。&lt;/p&gt;
&lt;p&gt;&amp;gt; まずMethodAについてです。&lt;/p&gt;
&lt;p&gt;&amp;gt; 「スレッドセーフなメソッド」のところに書いてある、&lt;/p&gt;
&lt;p&gt;&amp;gt; ”ローカル変数しか操作していないようなメソッドは、マルチスレッド動作せても問題がない。（※ ローカル変数が参照型で、そのオブジェクトインスタンスを別スレッドからも操作しせてたらダメですが；）” &lt;/p&gt;
&lt;p&gt;&amp;gt; という別のスレッドからの操作というのが気になりました。&lt;/p&gt;
&lt;p&gt;これは、例えば以下のような Web ページをマルチスレッド動作させた場合を考えてみるとわかりやすいと思います。&lt;/p&gt;
&lt;p&gt;public partial _Default : Page&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; private static MyClassA objA = new MyClassA();&lt;/p&gt;
&lt;p&gt; &amp;nbsp; protected void Page_Load(object sender, EventArgs e)&lt;/p&gt;
&lt;p&gt; &amp;nbsp; {&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp;MyClassA objX = objA;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp;objX.MethodZ();&lt;/p&gt;
&lt;p&gt; &amp;nbsp; }&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;この場合、objX はローカル変数（＝変数のハコはスレッドごとに作られる）ですが、実際に操作しているインスタンスは常に同じものになります。このため、この Web ページはマルチスレッド動作させた場合、（ローカル変数しか触っていないようなコードになっているけど）同一インスタンスを複数スレッドから操作することになる、というわけです。&lt;/p&gt;
&lt;p&gt;&amp;gt; ローカル変数が参照型でもスレッドごとに作成した場合はヒープ領域が別々で作られるなら（ここがわかりません）、MethodAもスレッドセーフなのではないかと思います。&lt;/p&gt;
&lt;p&gt;ローカル変数の「箱」はスレッドごとに作られますが、ヒープメモリ空間は、プロセス内にひとつ（正確には AppDomain 内にひとつ）です。よって、ローカル変数が参照型の場合には、&lt;/p&gt;
&lt;p&gt;・ローカル変数の「箱」（アドレス値を入れる箱）は、スレッドごとにできる。&lt;/p&gt;
&lt;p&gt;・でもインスタンスは、プロセス内の共有空間であるヒープ領域に作られる。&lt;/p&gt;
&lt;p&gt;となります。&lt;/p&gt;
</description></item><item><title>re: スレッドとオブジェクトインスタンス</title><link>http://blogs.msdn.com/nakama/archive/2008/12/18/9231090.aspx#9252528</link><pubDate>Thu, 25 Dec 2008 13:39:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9252528</guid><dc:creator>HashedBeef</dc:creator><description>&lt;p&gt;回答ありがとうございます！！&lt;/p&gt;
&lt;p&gt;さらに別のエントリまで作っていただいて…&lt;/p&gt;
&lt;p&gt;大変お手数をおかけしました＾＾；&lt;/p&gt;
&lt;p&gt;細かいところを気にする性分なもので、Essential .NET、読んでみたいと思います。&lt;/p&gt;
&lt;p&gt;私の疑問は続・スレッドとオブジェクトインスタンスのプールスレッドの図で大体解決したのですが、確認のため私なりにnakamaさんのまとめを編集してみました。&lt;/p&gt;
&lt;p&gt;・ローカル変数の「箱」（アドレス値を入れる箱）は、スレッドごとにスタックに作成される。&lt;/p&gt;
&lt;p&gt;・でもインスタンスは、プロセス内の共有空間であるヒープ領域に作られる。&lt;/p&gt;
&lt;p&gt;そしてインスタンス生成について以下のように場合わけできる&lt;/p&gt;
&lt;p&gt;　○(newで)新しく作られる場合&lt;/p&gt;
&lt;p&gt;　→ 共有ヒープ領域内に、各スレッドで生成されるたびにそれぞれ独立な実体として保持される＝スレッドセーフ&lt;/p&gt;
&lt;p&gt;　○既存のインスタンスを新しく宣言したインスタンス変数に代入する場合&lt;/p&gt;
&lt;p&gt;　→ 共有ヒープ領域内に保持される実体は、同一の実体を指す＝スレッドセーフではない&lt;/p&gt;
&lt;p&gt;こんな理解でいいでしょうか。&lt;/p&gt;
&lt;p&gt;また、nakamaさんが記述されたコードの&lt;/p&gt;
&lt;p&gt;private static MyClassA objA = new MyClassA();&lt;/p&gt;
&lt;p&gt;のstaticの部分を取ると、&lt;/p&gt;
&lt;p&gt;マルチスレッドでこのページが呼び出されてもスレッドセーフだと思われるのですがどうでしょうか!?&lt;/p&gt;
</description></item><item><title>re: スレッドとオブジェクトインスタンス</title><link>http://blogs.msdn.com/nakama/archive/2008/12/18/9231090.aspx#9254171</link><pubDate>Sat, 27 Dec 2008 10:11:02 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9254171</guid><dc:creator>nakama</dc:creator><description>&lt;p&gt;&amp;gt; HashedBeef さん&lt;/p&gt;
&lt;p&gt;いえいえ、エントリ読んでいただいてありがとうございます^^。&lt;/p&gt;
&lt;p&gt;さてご質問の件ですが、&lt;/p&gt;
&lt;p&gt;&amp;gt; ・ローカル変数の「箱」（アドレス値を入れる箱）は、スレッドごとにスタックに作成される。&lt;/p&gt;
&lt;p&gt;&amp;gt; ・でもインスタンスは、プロセス内の共有空間であるヒープ領域に作られる。&lt;/p&gt;
&lt;p&gt;はい、その通りです。&lt;/p&gt;
&lt;p&gt;&amp;gt; そしてインスタンス生成について以下のように場合わけできる&lt;/p&gt;
&lt;p&gt;&amp;gt; 　○(newで)新しく作られる場合&lt;/p&gt;
&lt;p&gt;&amp;gt; 　→ 共有ヒープ領域内に、各スレッドで生成されるたびにそれぞれ独立な実体として保持される＝スレッドセーフ&lt;/p&gt;
&lt;p&gt;えと、「共有ヒープ領域内に、各スレッドで生成されるたびにそれぞれ独立な実体として保持される」は正しいのですが、これをスレッドセーフとは呼びません。&lt;/p&gt;
&lt;p&gt;&amp;gt; 　○既存のインスタンスを新しく宣言したインスタンス変数に代入する場合&lt;/p&gt;
&lt;p&gt;&amp;gt; 　→ 共有ヒープ領域内に保持される実体は、同一の実体を指す＝スレッドセーフではない&lt;/p&gt;
&lt;p&gt;こちらも同様で、「共有ヒープ領域内に保持される実体は、同一の実体を指す」は正しいですが、「スレッドセーフではない」とは言いません（し、スレッドセーフでないとは限りません）。&lt;/p&gt;
&lt;p&gt;スレッドセーフという言葉は、「複数スレッドから同一インスタンスの同一メソッドを呼んでもトラブルが起きない」ことを指します。&lt;/p&gt;
&lt;p&gt;端的に言えば、クラスやそのメソッドの「特性」みたいなものなのですね。&lt;/p&gt;
&lt;p&gt;例えば一番最後の例の場合、「既存のインスタンスを新しく宣言したインスタンス変数に代入する場合には、共有ヒープ領域内に保持される実体は、同一の実体を指す」のは正しいのですが、そのインスタンスがたとえば string 型のインスタンスだった場合には、トラブルが起きません。なぜなら、string クラスのすべてのメソッドはスレッドセーフに作られているからです。&lt;/p&gt;
&lt;p&gt;&amp;gt; また、nakamaさんが記述されたコードの&lt;/p&gt;
&lt;p&gt;&amp;gt; private static MyClassA objA = new MyClassA();&lt;/p&gt;
&lt;p&gt;&amp;gt; のstaticの部分を取ると、&lt;/p&gt;
&lt;p&gt;&amp;gt; マルチスレッドでこのページが呼び出されてもスレッドセーフだと思われるのですがどうでしょうか!?&lt;/p&gt;
&lt;p&gt;はい、こちらは正解です。&lt;/p&gt;
</description></item><item><title>re: スレッドとオブジェクトインスタンス</title><link>http://blogs.msdn.com/nakama/archive/2008/12/18/9231090.aspx#9254212</link><pubDate>Sat, 27 Dec 2008 11:27:42 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9254212</guid><dc:creator>HashedBeef</dc:creator><description>&lt;p&gt;スレッドセーフについての認識が間違っていたようなので、もう少し勉強してみます。&lt;/p&gt;
&lt;p&gt;これからもちょくちょく参考にさせていただきます。&lt;/p&gt;
&lt;p&gt;ありがとうございました！&lt;/p&gt;
</description></item><item><title>re: スレッドとオブジェクトインスタンス</title><link>http://blogs.msdn.com/nakama/archive/2008/12/18/9231090.aspx#9255093</link><pubDate>Sun, 28 Dec 2008 23:57:52 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9255093</guid><dc:creator>だどさん</dc:creator><description>&lt;p&gt;丁寧な解説ありがとうございます。&lt;/p&gt;
&lt;p&gt;表現の問題だけなのかわかりませんが、疑問に思った点だけ記載させていただきます。。。&lt;/p&gt;
&lt;p&gt;「インストラクションポインタ（＝現在の実行行番号）は、あくまで行番号を示している」&lt;/p&gt;
&lt;p&gt;とあります。そこまでは 「行番号」 はインストラクションポインタのことをわかりやすく書いていただけなのかと思って読んでいました。が、「あくまで行番号」 と強調されていますが、実行時に 「ソースの行番号」 を保持しているのでしょうか？&lt;/p&gt;
</description></item><item><title>re: スレッドとオブジェクトインスタンス</title><link>http://blogs.msdn.com/nakama/archive/2008/12/18/9231090.aspx#9255313</link><pubDate>Mon, 29 Dec 2008 06:35:49 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9255313</guid><dc:creator>nakama</dc:creator><description>&lt;p&gt;&amp;gt; だどさん&lt;/p&gt;
&lt;p&gt;こんにちは。書き込みありがとうございます。&lt;/p&gt;
&lt;p&gt;&amp;gt;「インストラクションポインタ（＝現在の実行行番号）は、あくまで行番号を示している」&lt;/p&gt;
&lt;p&gt;&amp;gt;とあります。そこまでは 「行番号」 はインストラクションポインタのことをわかりやすく&lt;/p&gt;
&lt;p&gt;&amp;gt;書いていただけなのかと思って読んでいました。が、「あくまで行番号」 と強調されて&lt;/p&gt;
&lt;p&gt;&amp;gt;いますが、実行時に 「ソースの行番号」 を保持しているのでしょうか？&lt;/p&gt;
&lt;p&gt;正確には、「ソースコードの行番号」ではなく、ソースコードがコンパイルされることに&lt;/p&gt;
&lt;p&gt;よって生成されたバイナリである IL コードの行番号、になります。&lt;/p&gt;
&lt;p&gt;ただ、IL コード（中間バイナリ）のことを書き始めると話がややこしくなるので、ここでは&lt;/p&gt;
&lt;p&gt;ある程度まるめて「ソースコード」と書くことにしました。&lt;/p&gt;
&lt;p&gt;ここで「あくまで行番号」と書いたのは、インストラクションポインタが指し示すコードが&lt;/p&gt;
&lt;p&gt;インスタンスごとにわかれているわけではない、という意図で書いています。&lt;/p&gt;
</description></item><item><title>re: スレッドとオブジェクトインスタンス</title><link>http://blogs.msdn.com/nakama/archive/2008/12/18/9231090.aspx#9256269</link><pubDate>Tue, 30 Dec 2008 01:25:06 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9256269</guid><dc:creator>だどさん</dc:creator><description>&lt;p&gt;回答ありがとうございます。&lt;/p&gt;
&lt;p&gt;やはり初心者向けに解説記事を書くのは難しいものですね。&lt;/p&gt;
&lt;p&gt;ちなみに私も以前は MS にいて (サポートの CPR でした)、ダンプ解析とかやってたのですが、理解とずれたので質問させていただいた次第です。特に理解を正すこともなく、ホッとしました。&lt;/p&gt;
</description></item><item><title>マルチスレッド Windows フォームアプリケーションの開発</title><link>http://blogs.msdn.com/nakama/archive/2008/12/18/9231090.aspx#9518858</link><pubDate>Mon, 30 Mar 2009 16:14:20 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9518858</guid><dc:creator>とあるコンサルタントのつぶやき</dc:creator><description>&lt;p&gt;というわけでまたしてもかなり日にちが空いてしまいました；。年度末ということもあって仕事が立て込んでいたのですが、ほぼ一段落したので久しぶりにエントリを。どうしてもまとまった話題を書こうとすると時間がかかっちゃいますね．．．．&lt;/p&gt;
</description></item><item><title>タスクスレッドの起動方法</title><link>http://blogs.msdn.com/nakama/archive/2008/12/18/9231090.aspx#9528279</link><pubDate>Thu, 02 Apr 2009 04:10:07 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9528279</guid><dc:creator>とあるコンサルタントのつぶやき</dc:creator><description>&lt;p&gt;さて、前回のエントリでは、Windows フォーム内部におけるスレッドの構成や、メッセージループの働きなどについて解説しました。中でも重要なこととして、以下のようなキーポイントがありました。 UI スレッド上で、長時間処理を動かしてはならない。&lt;/p&gt;
</description></item></channel></rss>