マルチスレッド---命令再配置(happenbefore)の紹介


めいれいさいはいち
命令再配列(HappenBefore):実行コードの順序がコードを記述する順序と一致しない可能性があります.すなわち、仮想マシンがコード順序を最適化すると、命令再配列になります.すなわち、コンパイラまたはランタイム環境がプログラム性能を最適化するために取った命令を並べ替えて実行する手段である.
  • 仮想マシンレベルでは、メモリの操作速度がcpuの実行速度よりはるかに遅いことによるcpuの空きの影響を最小限に抑えるために、仮想機会は自分のルールに従ってプログラムの作成順序を乱します.すなわち、先に書く可能性があれば後で実行し、後で書く可能性があります.
  • ハードウェアの面では、cpuは受信した命令のセットをルールに従って並べ替えます.同様に、cpu速度がキャッシュ速度より速い理由に基づいて、上記の目的と似ています.ただし、cpuは毎回限られた範囲クラスでしか並べ替えられませんが、仮想マシンはより大きなレベルで、より多くの命令範囲で並べ替えることができます.

  • 例えば、マシンでは、コードの実行は4つのステップに分けられます.
  • 取得命令
  • 復号、翻訳命令、レジスタから値
  • をとる
  • 操作
  • 結果をレジスタ
  • に書き込む
    例えば、subTotal=price+fee;total +=subTotal; isDone = true; price+feeという文は計算の過程が遅いかもしれませんが、結果を書く前にisDoneと計算過程は関係がないことに気づき、性能を向上させるためにisDone=trueを先に実行しました.subTotalを書き戻してからtotal+=subTotal文を実行します.これは単一スレッドでは問題ありません.ただし、マルチスレッドでは、isDoneを含む条件文にtotalの値を変更する操作があると、結果が変化します.
    データ依存性2つのオペレーションが同じ変数にアクセスし、2つのオペレーションのうち1つが書き込みオペレーションである場合、この2つのオペレーションの間にデータ依存性があります.データ依存度は、次の3つのタイプに分けられます.
  • 先に書いてa=2を読む.b=a;
  • 先に読んでからa=bと書きます.b=2;
  • 先に書いてa=2と書きます.a=1;

  • 上記の3つの場合,2つの操作の順序を並べ替えると,プログラム実行の結果が変化する.一方、コンパイラとプロセッサは、データ依存関係がある2つの操作の実行順序を変更しません.
    ここではjavaプログラムの例を示します.
    package Ohter;
    /**
     *     :            
     *   :    
     * @author CR553
     *
     */
    public class HappenBefore {
    	public static int a=0;
    	public static boolean flag=false;
    		public static void main(String[] args) throws InterruptedException {
    			for(int i=0;i<10;i++)
    			{
    				a=0;
    				flag=false;
    				
    			//    	
    			Thread t1=new Thread(()->{
    				a=1;
    				flag=true;
    				
    			});
    			
    			//    
    			Thread t2=new Thread(()-> {
    				if(flag)//             ,             
    				{
    					a*=1;
    				}
    				//       !jvm    a*=1;             ,     a  
    				if(a==0)
    				{
    					System.out.println("happenBefore a-->"+a);//a     0 1  0   ; 1       if(a==0)   a*=1    ,      1
    				}
    			});
    			
    			t1.start();
    			t2.start();
    			
    			t1.join();//             
    			t2.join();
    			}
    		}
    }