同時トラップ-プロセッサの並べ替え
4499 ワード
同じtestオブジェクトのwriter()とreader()をそれぞれ呼び出すスレッドが2つあると仮定します.すみません、bの値は何ですか?
(a) 1 (b) 2 (c) 1 or 2
ここでは主にプロセッサの並べ替えの問題について説明します.現在のプロセッサは、命令の実行を加速させるために、一部の命令を並べ替えて実行します.
データ依存
データ依存は簡単な概念であり、前後の2行のコードがデータに依存しているかどうかを判断することである.例:
明らかに、c文で使用されるnum 1およびnum 2はaおよびbに依存する.
データ依存度は、次の3つに分けられます. 1 store - load 2 load - store 3 store - store
依存性があるかどうかをどのように判断するかは簡単で、2つの文の間に同じ変数が使われているかどうか、書き込み操作が使われているかどうかを判断するだけです.
Happen before
JVMはhappen beforeという概念を定義し、前の実行の結果が後の実行に表示されることを意味する.簡単に言えば、前の項目が実行されてから、後の項目が実行されます.しかし実際には処理速度を上げるためにJVMはこの概念を弱体化しており,データ依存の場合は前条の実行が完了してから後条を実行することができる.
次の例を見てください.
上記3つの文a,b,cが実行され,単一スレッドが順次実行される場合.
伝達性に基づいて、
c命令で使用されるnum 1およびnum 2は、明らかにaおよびbに依存し、典型的なstore−loadである.したがって、c命令は、aおよびbが実行されるまで待たなければならない.しかし、aおよびbにはデータ依存性がないため、JVMは、プロセッサがaおよびbを並べ替えることを可能にする.
ではhappen beforeはいったい何ですか?私の理解ではhappen beforeはJVMが最下位のメモリ制御に対して抽象的な概念である.コード順に基づいてhappen beforeの関係を判断することができます.一方、JVMの下位層では、実際の状況に応じて異なるactionが実行されます(たとえば、メモリバリア、プロセッサバリアを追加したり、再ソートを阻止したり、プロセッサのフラッシュソートを許可したりします).この層により、メモリ制御がプログラマーに透明になり、プログラマーもコードの実際の実行状況を考慮する必要がなくなり、JVMは単一スレッドの実行が成功することを保証します.as-if-serial.
JVMがメモリ制御を透過している以上、なぜJVMが単一スレッドの実行に成功することを保証し、マルチスレッド環境では様々な問題が発生するのかを明らかにする必要があります.
答え
最初のテーマを上記で分析します.
Aスレッド実行:
Bスレッド実行:
1.多くの人が考えている状況を先に考慮する:命令順序:(1)->(2)->(3)->(4),b=1+1=2
2.予想外の状況Aスレッドでは、文(1)と(2)にデータ依存性の問題はありません.したがって、プロセッサは、命令(2)が命令(1)より先に実行される可能性があることを並べ替えることができます.命令が(2)->(3)->(4)->(1)の順で、b=0+1=1
3.Bスレッドの場合、プロセッサは(4)を前に処理し、結果をROBに配置し、制御文(3)が真である場合、結果をROBから取り出してそのまま使用する場合もある.これは最適化技術であり、予測である.したがって、命令の実行順序は(4)->x->x->x->x
4つの文が最初に実行される可能性があるようです.
まとめると,マルチプロセッサ環境では,各プロセッサに独自の読み書きキャッシュ領域があるため,一部のデータが一致しない.JMMは一連のactionでデータの一貫性を保証しますが、マルチスレッド環境では奇妙な問題が多く発生します.このときはプロセッサ、コンパイラの並べ替えを考慮します.
(a) 1 (b) 2 (c) 1 or 2
public class test{
private boolean flag = false;
private int a = 0;
public void writer(){
a = 1;
flag = True;
}
public void reader(){
if (flag){
b = a + 1
}
}
}
ここでは主にプロセッサの並べ替えの問題について説明します.現在のプロセッサは、命令の実行を加速させるために、一部の命令を並べ替えて実行します.
データ依存
データ依存は簡単な概念であり、前後の2行のコードがデータに依存しているかどうかを判断することである.例:
num1 = 1 // (a)
num2 = 2 // (b)
result = num1 + num2 // (c)
明らかに、c文で使用されるnum 1およびnum 2はaおよびbに依存する.
データ依存度は、次の3つに分けられます.
依存性があるかどうかをどのように判断するかは簡単で、2つの文の間に同じ変数が使われているかどうか、書き込み操作が使われているかどうかを判断するだけです.
Happen before
JVMはhappen beforeという概念を定義し、前の実行の結果が後の実行に表示されることを意味する.簡単に言えば、前の項目が実行されてから、後の項目が実行されます.しかし実際には処理速度を上げるためにJVMはこの概念を弱体化しており,データ依存の場合は前条の実行が完了してから後条を実行することができる.
次の例を見てください.
num1 = 1 // (a)
num2 = 2 // (b)
result = num1 + num2 // (c)
上記3つの文a,b,cが実行され,単一スレッドが順次実行される場合.
a happen before b
b happen before c。
伝達性に基づいて、
a happen before c
c命令で使用されるnum 1およびnum 2は、明らかにaおよびbに依存し、典型的なstore−loadである.したがって、c命令は、aおよびbが実行されるまで待たなければならない.しかし、aおよびbにはデータ依存性がないため、JVMは、プロセッサがaおよびbを並べ替えることを可能にする.
a -> b -> c = 3
b -> a -> c = 3
ではhappen beforeはいったい何ですか?私の理解ではhappen beforeはJVMが最下位のメモリ制御に対して抽象的な概念である.コード順に基づいてhappen beforeの関係を判断することができます.一方、JVMの下位層では、実際の状況に応じて異なるactionが実行されます(たとえば、メモリバリア、プロセッサバリアを追加したり、再ソートを阻止したり、プロセッサのフラッシュソートを許可したりします).この層により、メモリ制御がプログラマーに透明になり、プログラマーもコードの実際の実行状況を考慮する必要がなくなり、JVMは単一スレッドの実行が成功することを保証します.as-if-serial.
JVMがメモリ制御を透過している以上、なぜJVMが単一スレッドの実行に成功することを保証し、マルチスレッド環境では様々な問題が発生するのかを明らかにする必要があります.
答え
最初のテーマを上記で分析します.
Aスレッド実行:
public void writer(){
a = 1; // (1)
flag = True; // (2)
}
Bスレッド実行:
public void reader(){
if (flag){ // (3)
b = a + 1 // (4)
}
}
1.多くの人が考えている状況を先に考慮する:命令順序:(1)->(2)->(3)->(4),b=1+1=2
2.予想外の状況Aスレッドでは、文(1)と(2)にデータ依存性の問題はありません.したがって、プロセッサは、命令(2)が命令(1)より先に実行される可能性があることを並べ替えることができます.命令が(2)->(3)->(4)->(1)の順で、b=0+1=1
3.Bスレッドの場合、プロセッサは(4)を前に処理し、結果をROBに配置し、制御文(3)が真である場合、結果をROBから取り出してそのまま使用する場合もある.これは最適化技術であり、予測である.したがって、命令の実行順序は(4)->x->x->x->x
4つの文が最初に実行される可能性があるようです.
まとめると,マルチプロセッサ環境では,各プロセッサに独自の読み書きキャッシュ領域があるため,一部のデータが一致しない.JMMは一連のactionでデータの一貫性を保証しますが、マルチスレッド環境では奇妙な問題が多く発生します.このときはプロセッサ、コンパイラの並べ替えを考慮します.