この記事はHUAWEICLOUDコミュニティから共有されています" [高い同時実行性]ローカル変数がスレッドセーフなのはなぜですか?"、著者:氷河。
序文
複数のスレッドが同時に共有変数にアクセスすると、同時実行の問題が発生する可能性があります。したがって、変数がメソッド内に配置されている場合でも、並行性の問題はありますか?並行性の問題がない場合、なぜ並行性の問題がないのですか?
有名なフィボナッチ数列
私たちが学校にいたとき、私たちは皆、フィボナッチ数列を印刷するというそのような問題に遭遇したことを覚えています。フィボナッチ数列は次のような数列です:1、1、2、3、5、8、13、21、34 ...つまり、1番目と2番目の項目は1で、3番目の項目から始まります。前の2つの項目の合計に等しい。次のコードを使用して、フィボナッチ数列を生成できます。
//生成斐波那契数列
public int[] fibonacci(int n){
//存放结果的数组
int[] result = new int[n];
//数组的第1项和第2项为1
result[0] = result[1] = 1;
//计算第3项到第n项
for(int i = 2; i < n; i++){
result[i] = result[i-2] + result[i-1];
}
return result;
}
フィボナッチ数列を生成するために同時にfibonacci()メソッドを呼び出すスレッドが多数あるとすると、メソッドのローカル変数の結果にスレッドセーフの問題が発生しますか?答えはいいえだ!!
次に、ローカル変数にスレッドセーフの問題がない理由を詳しく分析します。
メソッドはどのように実行されますか?
例として、次の3行のコードを取り上げます。
int x = 5;
int[] y = fibonacci(x);
int[] z = y;
fibonacci(x)を呼び出す場合、CPUは最初にfibonacci()メソッドのアドレスを見つけ、次にこのアドレスにジャンプしてコードを実行する必要があります。実行後、CPUは戻って、次のステートメントのアドレスを見つける必要があります。 int [] z = yのアドレスであるメソッドを呼び出し、このアドレスにジャンプして実行します。次の図に示すように、このプロセスを簡略化できます。
ここで、CPUはスタックレジスタを介して呼び出し元のメソッドのパラメータとリターンアドレスを見つけることに注意してください。
たとえば、A、B、Cの3つのメソッドがあり、呼び出し関係は、AがBを呼び出し、BがCを呼び出すというものです。実行時に、対応する呼び出しスタックが構築されます。次の図を使用して、この呼び出しスタックを簡単に表すことができます。
各メソッドは、呼び出しスタックに独自の独立したスタックフレームを持ち、各スタックフレームには、対応するメソッドに必要なパラメーターとリターンアドレスがあります。メソッドが呼び出されると、新しいスタックフレームが作成され、呼び出しスタックにプッシュされます。メソッドが戻ると、対応するスタックフレームが自動的にポップされます。
これは、メソッドが呼び出されたときにスタックフレームが作成され、メソッドが戻ったときに「終了」すると言うことができます。
ローカル変数はどこに保存されますか?
ローカル変数のスコープはメソッド内にあります。メソッドを実行すると、ローカル変数は役に立ちません。メソッドが戻ると、ローカル変数は「死ぬ」と言えます。この時点で、呼び出しスタックのスタックフレームについて考えます。はい、ローカル変数は呼び出しスタックに格納されます。この時点で、メソッドの呼び出しスタックを次の図で表すことができます。
多くの人は、ローカル変数がスタックに格納されていることを知っています。変数がメソッドの境界を越える必要がある場合は、ヒープ上に作成する必要があります。
スタックとスレッドを呼び出す
2つのスレッドは、異なるパラメーターを使用して同じメソッドを同時に呼び出すことができます。だから問題は、コールスタックとスレッドの関係は何ですか?答えは次のとおりです。各スレッドには独自の独立した呼び出しスタックがあります。次の図を使用して、この関係を簡単に表すことができます。
この時点で、次の最初の質問を検討しています。Javaメソッド内のローカル変数に並行性の問題がありますか?答えは、並行性の問題はないということです。各スレッドには独自の呼び出しスタックがあるため、ローカル変数はスレッドのそれぞれの呼び出しスタックに格納され、共有されません。したがって、当然、同時実行の問題はありません。
スレッドクロージャー
メソッド内のローカル変数は他のスレッドと共有されないため、同時実行の問題は発生しません。この問題解決手法は、スレッドの制限とも呼ばれます。公式の説明は次のとおりです。単一のスレッド内でのみデータにアクセスします。共有がないため、同期を設定しなくても同時実行の問題はありません。