JAvaは可視性と秩序性の問題をどのように解決しますか?--学習ノート


JAvaは可視性と秩序性の問題をどのように解決しますか?
  • 記事を通してhttps://blog.csdn.net/qq_33249725/article/details/89482779)
  • から分かるように、Cpuキャッシュは可視性の問題を引き起こし、コンパイラの最適化は秩序性の問題を引き起こし、私たちが直接連想できる解決方法はCpuキャッシュとコンパイラの最適化を無効にすることですが、このようにプログラムの実行効率が低くなり、カスタマイズして無効にすることができますか?次はJavaメモリモデルです.

  • JAvaメモリモデル
  • は、必要に応じてCpuキャッシュとコンパイラの最適化を無効にし、javaメモリモデルは、volatile、synchronized、finalの3つのキーワード、およびHappens-Beforeルールを含むJVMが必要に応じてキャッシュとコンパイラの最適化を無効にする方法を仕様しています.

  • volatileキーワード
  • volatileはjavaの特産品ではなく、C言語の時からこのキーワードがあり、volatileによって定義された変数は他のスレッドですぐに知ることができる(volatileによって修飾された変数は書くときにメモリを直接操作し、他のスレッドは読むときも最新の値を読み取るため)
  • volatileとsynchronizedの違いvolatileは可視性を保証しているが原子性を保証できず、性能はsynchronizedより高い.スレッド切替が発生しないため、synchronizedは原子性を保証するだけでなく、可視性も保証している.
  • volatileキーワードを使用する場合も困りますJDK 1.5以前の場合、具体的には、
  • のコード例を参照してください.
    class VolatileExample {
      int x = 0;
      volatile boolean v = false;
      public void writer() {
        x = 42;
        v = true;
      }
      public void reader() {
        if (v == true) {
          //    x      ?
        }
      }
    }
    

    例説明:スレッドAがwriter()操作を実行する場合、スレッドBがreader()メソッドを実行する場合、Xはどのくらいになりますか?JDK 1.5より前のXの値は0か42かもしれませんが、なぜ0が発生したのでしょうか.可視性の問題で、スレッドAでwriter()メソッドを実行してXを書き込み、Cpuキャッシュで行い、メモリにリフレッシュされていないスレッドBで読み取りを実行したのは、メモリにリフレッシュされていない0である可能性があります.JDK 1.5とJDK 1.5以降のXの値は42にすぎません.JDK 1のためです.5以降volatileを強化し,Happens−Before仕様を追加した.
    Happens-Before
  • プログラムの順序規則はプログラム順序に従い、前の操作Happens-Beforeは後続の任意の操作である.
  • というのは、前の変数に対する操作が後続の可視化に対して、単一スレッドの実行論理と似ていることをよく理解しています.

  • 伝達性字面の意味がよく理解されているのは可視性の伝達である.
  • A Happens−Before B,B Happens−Before Cの場合、A Happens−Before c、すなわちAの動作はCに対して可視である.上記コードの例:X=42 Happens-Before V=true V=true Happens-Before V=true(これはよく理解されるべきで、前読み後に書く)伝達性の特性:X=42 Happens-Before V=true、すなわちX=42対V=trueが見えるのでJDK 1.5の場合上記コードXの可能性は42である.

  • volatile変数規則
  • volatile修飾変数書き込み操作後続のこの変数の読み取り操作が見られるが、これは
  • をよく理解すべきである.
  • ロックのルール
  • この規則は、個のロックに対するロック解除動作が後続のこのロックに対して表示されることを意味する.
  • 例を挙げると、スレッドA取得ロック共有変数x(初期は0)の値を10にし、操作が完了するとロックを解放し、スレッドB取得ロックは、Xが10.
  • に等しいことがすぐにわかる.

  • スレッドstart()ルール
  • 主スレッドAがサブスレッドBを起動することを指す場合、Bスレッドは主スレッドAがサブスレッドBを起動する動作を見ることができる.
  • 主線Aは、サブスレッドを起動すると共有変数x(初期は0)の値を10とし、メインスレッドAがサブスレッドBを起動すると、スレッドBは共有変数xの値を10とすることができる.

  • スレッドのjoin()ルール
  • は、メインスレッドAがサブスレッドBの完了を待つと、メインスレッドがサブスレッドの動作を見ることができることを指す.
  • 例として、サブスレッドが共有変数xを操作してx(初期は0)の値を10に設定し、メインスレッドがサブスレッドBのjoinメソッドを呼び出すと、xの値が10であることがわかる.

  • スレッド割込み規則
  • スレッドinterrupt()メソッドの呼び出しは、割り込みスレッドのコードによって割り込みイベントの発生が検出された場合に先行する、Thread.interrupted()メソッドは、割り込みが発生したかどうかを検出します.

  • オブジェクト終端規則
  • オブジェクトの初期化完了(コンストラクション関数実行終了)は、そのfinalize()メソッドの開始に先行して発生する.


  • finalキーワード
  • finalキーワード修飾の変数は可変であり,換言すれば可視性を保つことができる.

  • まとめ
  • 本稿の学習ノートはjavaが可視性と原子性の問題をどのように処理するかを記録しており、javaの同時プログラミングを本当に学ぶには、その原理が第一歩であることを理解し、重点的に実践するかを理解するには、ビジネスを書くと同時に、ビジネス自体の論理以外にデータの安全性の問題を考慮することができます.