2009-03-25 26 views
6

静的関数を同時に呼び出す2つのスレッドがある場合は、並行処理のリスクはありますか?その関数がクラスの静的メンバーを使用する場合、さらに大きな問題がありますか?静的関数同時実行性ASP.NET

  • 2つのコールは互いに分離されていますか? (この関数は2つのスレッドに対してコピーされたようなものです)
  • これらは自動的にキューに入れられますか?

たとえば、次の例では、リスクはありますか?

private static int a = 5; 

public static int Sum() 
{ 
    int b = 4; 
    a = 9; 
    int c = a + b; 
    return c; 
} 

次の例では、リスクはありますか?

public static int Sum2() 
{ 
    int a = 5; 
    int b = 4; 
    int c = a + b; 
    return c; 
} 

更新:そして実際、両方の機能が同じクラスにある場合、リスクは、何ですか?あなたは、静的メソッドで静的変数を変更すると

THX、リーフェンCardoen

答えて

10

はい、並行性のリスクがあります。

静的関数自体には別個のローカル変数がありますが、静的変数はすべて共有されています。

特定のサンプルでは、​​公開されていませんが、それは定数を使用しているため(同じ値を割り当てているため)です。コードサンプルを少し変更すると、公開されます。

編集:あなたは、あなたが困っている別のスレッドからSum1と()AND SUM2()両方を呼び出す場合

、この声明の中での値aとbを保証する方法はありません。int c = a + b;

private static int a = 5; 

public static int Sum1() 
{ 
    int b = 4; 
    a = 9; 
    int c = a + b; 
    return c; 
} 

public static int Sum2() 
{ 
    int b = 4; 
    int c = a + b; 
    return c; 
} 

また、このような単一のメソッドの複数の呼び出しと並行性の問題を達成することができます

public static int Sum3(int currentA) 
{ 
    a = currentA; 
    int b = 4; 
    int c = a + b; 
    int d = a * b; // a may have changed here 
    return c + d; 
} 

ここでの問題は、の値がために、他に半ば方法を変更することがありますそれを変更する呼び出し。

+0

私は最初の例を変更しました。今はおそらくスレッドセーフではないでしょうか? –

+0

このトピックの周りに良い参考文献、本、リンクがありますか?これらの状況にどのように対処できますか? –

+0

http://www.amazon.com/Concurrent-Programming-Java-TM-Principles/dp/0201310090/ref=pd_bbs_sr_3?ie=UTF8&s=books&qid=1237967873&sr=8-3あなたによく役立つはずです – krosenvold

1

あなたの2つの例では、関数の各呼び出しにはスタック上のローカル変数のコピーがあり、最初の例では 'a'は静的変数であるため、 'a'を変更しても問題ありません。

最初の例で 'a'の値を変更すると、並行性の問題が発生する可能性があります。

+0

Trueは、変数Aが変更されていないことに気付かなかったので、私たちが見ることのできるコードではすべてが良好です。潜在的に可視コードの外で修正される可能性があります –

+0

変更されました。ごめんなさい。最初の例はうまくいきませんでした。 –

1

変数の範囲は、静的関数内に含まれている場合、危険性はないが、機能範囲(静的/共有)の外部変数は、間違いなく並行性リスク

3

ポーズはい、危険性があります。そのため、MSDNのドキュメントでは、「このクラスは静的メンバーにとってスレッドセーフです」などとよく言われます。これは、MSがコードを書いたときに、意図的に同期プリミティブを使用して静的メンバーをスレッドセーフにすることを意味します。これは、ライブラリー・ユーザーがインスタンスでやりたいことがわからないため、静的メンバーをインスタンス・メンバーよりもスレッドセーフにするほうが簡単なため、ライブラリーおよびフレームワークの作成時によく使用されます。もしそれらがインスタンスメンバーをライブラリクラスの多くに対してスレッドセーフなものにしてしまうと、あなたにはあまりにも多くの制限がかかってしまいます。

同様に、静的メンバーをスレッドセーフにする(またはそうでないことを文書化する)必要があります。

ところで、スタティックコンストラクタは意味でスレッドセーフです。 CLRは、それらが一度だけ呼び出され、2つのスレッドが静的なコンストラクタに入るのを防ぎます。

EDIT:Marcは、静的コンストラクタがスレッドセーフではないエッジケースをコメントで指摘しました。リフレクションを使用して静的コンストラクタを明示的に呼び出す場合は、それを複数回呼び出すことができます。したがって、私は次のようにステートメントを改訂します。CLRを使用して静的なコンストラクタを呼び出すタイミングを決定する限り、CLRは複数回呼び出されないようにし、静的な呼び出しが呼び出されるのを防ぎますリエントラント。

+0

実際、これは*保証*していません - あなたはリフレクションを介して型初期化子を呼び出すことができます。この場合、一度に複数回呼び出すことができます。 –

+0

ああ、興味深い。私はそれを考えなかった。いい視点ね。それでも、リフレクションによって明示的に呼び出さない限り、CLRを使用してスレッドセーフにすることができます。時には便利です。 –

3

ローカル変数については、hereを参照してください。 編集前上記のいずれの方法も自身は並行性のリスクを示しました。ローカル変数はすべて呼び出しごとに独立しています。共有状態(static int a)は複数のスレッドから見ることができますが、変更しておらず、一度だけ読み込みます。

あなたが何かやった場合:

if(a > 5) { 
    Console.WriteLine(a + " is greater than 5"); 
} // could write "1 is greater than 5" 

の値が別のスレッドによって変更される可能性があるので、それは(理論的に)は、安全ではありません - あなたは、一般的にlock経由(アクセスを同期することになるのいずれかスナップショットを取る:

int tmp = a; 
if(tmp > 5) { 
    Console.WriteLine(tmp + " is greater than 5"); 
} 

値を編集する場合は、ほとんどの場合、同期が必要です。

+0

Thx。編集のために申し訳ありません。 –

1

OOの静的メソッドは、手続き型プログラミングの「単なる」関数と違いはありません。静的変数の中にある状態を保存しない限り、リスクはまったくありません。あなたは質問のタイトルに「ASP.NET」を入れ

関連する問題