web-dev-qa-db-ja.com

2つのスレッドが同じ静的メソッドを同時に呼び出すとどうなりますか?

2つのスレッドが同じ静的メソッドを同時に呼び出すとどうなりますか?例えば:

public static String someMethod(){

    //some logic, can take about 1 second to process

    return new String(result);
}

最初のスレッドはsomeMethod()を呼び出します。 2番目のスレッドは0.5秒後にsomeMethod()を呼び出します(最初のスレッドはまだデータを処理しています)。

SomeMethod()を同期できることは知っています。しかし、同期されていない場合はどうなりますか?

17

メソッドが状態外で変化するかどうかによって異なります。

static long i = 0l;
public static String someMethod(){
    String accm = "";
    for(;i < Integer.MAX_VALUE*20/*Just to make sure Word tearing occurs*/; i++)
        accm += i
    return accm;
}

問題が発生します:

  • ロングはアトミックに設定されることが保証されていないため、「引き裂かれた」可能性があります( Spec
  • ++はアトミック操作ではありません。 {int n = i; i = i + 1; return n} とまったく同じです。
    • i = i + 1もアトミックではありません。途中で変更すると、一部の値が繰り返されます
    • Nの戻りは古くなっている可能性があります

ただし、iがローカル変数の場合、問題はありません。読み取り中に外部状態が不変であることが保証されている限り、問題が発生することはありません。

12
user60561

メソッドが呼び出されると、JVMは実行中のスレッドでの呼び出しに対してスタックフレームを作成します。このフレームには、メソッドで宣言されたすべてのローカル変数が含まれています。フィールドにアクセスしない静的またはその他のメソッドの場合、各実行は各スレッドで完全に独立して進行します。メソッドが計算にパラメーターを使用する場合、これらのパラメーターもスタックフレームに配置され、複数の呼び出しが互いに干渉することはありません。

24

メソッドが静的であるという事実は関係ありません。彼らの質問は、問題のコードによって操作されている状態変数である必要があります。

  • インスタンス/クラスのメンバーが読み取り/書き込みされていない場合は、問題はありません。
  • 書き込み操作の場合、何らかの同期が必要です
  • 読み取りのみがある場合、それは必ずしもメソッドが適切に同期されていることを意味するわけではありません。これは、データがどのように書き込まれ、どのスレッドによって書き込まれるかによって異なります。たとえば、コードが書き込み操作中にモニターMによって保護されているVを読み取る場合、Vの読み取りも同じモニターで同期する必要があります。
4
Eyal Schneider

2つのステートメントが別々のスレッドで実行される場合、happens-beforeを確立しない限り、最初のスレッドの変更が2番目のスレッドに表示される保証はありません。特定の同期戦略を使用してsomeMethod()を同期することによる、これら2つのステートメント間の関係。つまり、同じ変数に書き込んでから2つのスレッドから同時に読み取る場合、ロジックは予期しない予測できない結果をもたらす可能性があります。

0
wypieprz