ローカル変数がスレッドセーフである理由を知っていますか?

序文

複数のスレッドが同時に共有変数にアクセスすると、同時実行の問題が発生します。したがって、変数がメソッド内に配置されている場合でも、同時実行の問題はありますか?同時実行の問題がない場合、なぜ同時実行の問題がないのですか?

Javaの知識やインタビューの質問がもっと必要な友達は、下のリンクをクリックして無料で入手できます。

リンク:1103806531パスワード:CSDN

ここに写真の説明を挿入

有名なフィボナッチシーケンス

私たちが学校にいたとき、私たちは皆、フィボナッチシーケンスを印刷するというそのような問題に遭遇したことを覚えています。フィボナッチシーケンスは次のようなシーケンスです:1、1、2、3、5、8、13、21、34 ...、つまり、第1項と第2項は1であり、第3項から始まります。 1つの項目は、前の2つの項目の合計に等しくなります。次のコードを使用して、Fibonacciシーケンスを生成できます。

//生成斐波那契数列
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()メソッドを呼び出して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を呼び出すというものです。実行時に、対応するコールスタックが構築されます。次の図を使用して、このコールスタックを表すことができます。

ここに写真の説明を挿入
各メソッドには、呼び出しスタック内に独自の独立したスタックフレームがあり、各スタックフレームには、対応するメソッドに必要なパラメーターと戻りアドレスがあります。メソッドが呼び出されると、新しいスタックフレームが作成され、呼び出しスタックにプッシュされます。メソッドが戻ると、対応するスタックフレームが自動的にポップアウトされます。

これは、メソッドが呼び出されたときにスタックフレームが作成され、メソッドが戻ったときに「死ぬ」と言うことができます。

ローカル変数はどこに保存されますか?

ローカル変数のスコープはメソッド内にあります。メソッドが実行されると、ローカル変数は役に立ちません。メソッドが戻ると、ローカル変数「die」と言えます。ここでは、コールスタックのスタックフレームについて考えます。はい、ローカル変数はコールスタックに保存されます。この時点で、次の図を使用して、メソッドの呼び出しスタックを表すことができます。

ここに写真の説明を挿入

多くの人は、ローカル変数がスタックに格納されていることを知っています。変数がメソッドの境界を越える必要がある場合は、ヒープ内に作成する必要があります。

スタックとスレッドを呼び出す

2つのスレッドは、異なるパラメーターを使用して同じメソッドを同時に呼び出すことができます。だから問題は、コールスタックとスレッドの間の関係は何ですか?答えは次のとおりです。各スレッドには独自の独立した呼び出しスタックがあります。次の図を使用して、この関係を簡単に表すことができます。

ここに写真の説明を挿入
この時点で、次の冒頭の質問を検討しています。Javaメソッド内のローカル変数に同時実行性の問題がありますか?答えは、同時実行の問題はないということです。各スレッドには独自の呼び出しスタックがあるため、ローカル変数はスレッドのそれぞれの呼び出しスタックに格納され、共有されません。当然、同時実行の問題はありません。

スレッドクロージャー

メソッド内のローカル変数は他のスレッドと共有されないため、同時実行の問題は発生しません。この問題解決手法は、スレッドクロージャとも呼ばれます。公式の説明は次のとおりです。単一のスレッドでのみデータにアクセスします。共有がないため、同期が設定されていなくても同時実行性の問題はありません!

やっと

また、Javaのコア知識ポイント、インタビュートピック、最新のインターネットの実際の質問や電子書籍など、建築家向けのビデオチュートリアルとJavaに関する体系的な資料のフルセットを20年間編集しました。困っている友達は下のリンクをクリックして無料で入手できます!

リンク:1103806531パスワード:CSDN

ここに写真の説明を挿入

ここに写真の説明を挿入

おすすめ

転載: blog.csdn.net/XingXing_Java/article/details/109278934