Java共有変数の可視性研究(一)


1.メインスレッドで別のスレッドthread 1を起動する
public static void main(String[] args) {
        Runnable demo = new MyRunnable(bonkBean);
        Thread thread = new Thread(demo,"thread1");
        /*try {
            Thread.sleep(1000);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }*/
        flag = true;
        thread1.start();
   
        /*try {
            Thread.sleep(5000);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }*/
    }
    
    private static class MyRunnable implements Runnable {  
        @Override
        public void run() {
            //System.out.println(Thread.currentThread().getName() + ":" + flag);
            //synchronized (AbstractThriftCodecManagerTest.class){}
            while (true) {
                //synchronized (AbstractThriftCodecManagerTest.class){}
                if (flag) {
                    break;
                }
            }
            System.out.println("    ");
            // System.out.println(Thread.currentThread().getName()+":"+ a);
        }
    }

  通常の状況では、flagはベースタイプ変数としてメインスレッドとスレッド1によってワークメモリにコピーされるため、メインスレッドがflagをtrueに変更した後、必ずメインメモリに書き込まれるとは保証されないため、スレッド1は常に実行されることが多い.ただし、メインスレッドがflagをtrueに設定してスレッド1を再起動すると、スレッド1は直ちに実行終了する.理由は次のとおりです.JavaメモリモデルはHappens-Beforeルールに従います.スレッド起動の原則があります.すなわち、startメソッドを呼び出すと、startメソッドの前のすべての操作の結果がメインメモリに同期され、新しいスレッドが作成された後、メインメモリからデータを取得する必要があります.これにより、startメソッド呼び出し前のすべての操作結果が、新しく作成されたスレッドに対して表示されます.したがって、スレッド1が起動すると、読み込まれたflag変数はtrueとなる.このhappens-beforeの原則を検討する前に、マスタースレッドから起動したスレッド1がマスタースレッドのflagコピーの値をコピーしたかどうかを考慮したことがあります.すなわち、サブスレッドとは親スレッドの一部のリソースを継承していますが、最後に親子スレッド継承とは関係ないことがわかりました.ただし、ThreadLocalから継承されたInheritableThreadLocalというクラスは、サブスレッド初期化時に親スレッドのInheritableThreadLocalタイプ変数をコピーする目的を達成し、継承を実現できることも知られている.拡張リンク:1、https://www.cnblogs.com/cookiezhi/p/5774583.html