none
マルチスレッドアプリケーションでの適切なlockのかけ方 RRS feed

  • 質問

  • winxp+sp2

    VS2005 C#

    次のようなクラスがあります。

    static class sample {

            private static object m_lock = new object();

            private static string m_RetVal2 = "";
     
            static sample() {}

            public static string test(string val1, string val2){
                string Ret = "";
                string Retval1 = "";

                lock (m_lock) {
                    Retval1 = val1;
                    m_RetVal2 = val2;
                }

                Ret = Retval1 + m_RetVal2;
                return Ret;
            }
        }

     

    マルチスレッドでtest()メソッドを複数のスレッドから呼び出します。

    スレッド1    string val = sample .test("A", "B")

    スレッド2    string val = sample .test("c", "d")

     

    スレッド1は結果として"AB"をスレッド1は結果として"cd"を受け取りたいのですが、m_RetVal2 はprivate変数なので"B"と"d"がメソッド実行のタイミングにより入れ替わってしまう事があると思います。(防ぐにはreturnもlockに入れてしまえばいいと思います。)

    今回教えて頂きたいのは、"A"と"c"がメソッド実行のタイミングにより入れ替わってしまう事があるかどうかです。入れ替わる事は無いだろうと考えていますが、知っている人がいましたら宜しくお願いします。

    また、この状況の場合スレッド1とスレッド2から呼び出されたメソッドはどこまでが共通のメモリを使用され、どこまでが個別のメモリを使用されるのかも教えて頂ければと思います。

     

    2007年2月2日 15:02

回答

  •  MSshingo さんからの引用

    これはローカル変数(引数も)はメソッドを呼び出すスレッド毎に別のメモリ領域に作成されているからなんでしょうか?

    ローカル変数はスタック上に確保されます。スタックはスレッド毎に用意されていますから、互いに干渉することを避けられたのでしょう。

    対象がヒープ上に確保されている場合、ヒープはスレッド間で共有されていますから注意が必要になります。例えば m_Retval は呼び出しスレッドに関わらず同じ場所に確保されていますので、タイミングによって入れ替わってしまうことがあります。

     

    2007年2月2日 17:50
  •  MSshingo さんからの引用

    また、この状況の場合スレッド1とスレッド2から呼び出されたメソッドはどこまでが共通のメモリを使用され、どこまでが個別のメモリを使用されるのかも教えて頂ければと思います。

    メモリの共有と、スレッドは直接は関係していません。

    各静的変数は各プロセスにひとつしかなく、動的変数はそのメソッドに入るごとにスタック上に確保されます(同じスレッドからでも、そのメソッド中でも)。動的変数は間接参照されていない限り、揮発性について考慮する必要はありません。

    2007年2月2日 18:03

すべての返信

  • 一応サンプル作って確認してみました。

    "A"と"c"がメソッド実行のタイミングにより入れ替わってしまう事はないようですね。

    これはローカル変数(引数も)はメソッドを呼び出すスレッド毎に別のメモリ領域に作成されているからなんでしょうか?

    2007年2月2日 15:41
  •  MSshingo さんからの引用

    これはローカル変数(引数も)はメソッドを呼び出すスレッド毎に別のメモリ領域に作成されているからなんでしょうか?

    ローカル変数はスタック上に確保されます。スタックはスレッド毎に用意されていますから、互いに干渉することを避けられたのでしょう。

    対象がヒープ上に確保されている場合、ヒープはスレッド間で共有されていますから注意が必要になります。例えば m_Retval は呼び出しスレッドに関わらず同じ場所に確保されていますので、タイミングによって入れ替わってしまうことがあります。

     

    2007年2月2日 17:50
  •  MSshingo さんからの引用

    また、この状況の場合スレッド1とスレッド2から呼び出されたメソッドはどこまでが共通のメモリを使用され、どこまでが個別のメモリを使用されるのかも教えて頂ければと思います。

    メモリの共有と、スレッドは直接は関係していません。

    各静的変数は各プロセスにひとつしかなく、動的変数はそのメソッドに入るごとにスタック上に確保されます(同じスレッドからでも、そのメソッド中でも)。動的変数は間接参照されていない限り、揮発性について考慮する必要はありません。

    2007年2月2日 18:03
  • Takashi SAKAMOTOさん、Kazuya Ujiharaさん回答ありがとうございました。

    今回のケースでは、ローカル変数は影響を受けないということですね。

     

    2007年2月4日 8:03