JAva高同時プログラミング-violateキーワード使用シーン
1819 ワード
package com.fsun.research.thread.violate;
public class MainTest {
private static boolean ready;
private static class CounterThread implements Runnable{
@Override
public void run() {
while(!ready){
}
}
}
public static void main(String[] args) {
new Thread(new CounterThread()).start();
System.out.println(" 300 ");
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
ready=true;
}
}
上記の例ではrunメソッドがデッドサイクルに陥るのは、CounterThreadスレッドは、メインスレッドがready値を変更する前にメインメモリからreadyの値を自分のワークメモリに読み出していたため(メインスレッドが300ミリ秒眠るのはそれを保証するため)、whileサイクルで大量のサイクル読み出しが止まらないため、jvmは読み取り効率を向上させるため、このような高同時読み取りの場合はスレッドのワークメモリから読み取り、プライマリスレッドが眠りから覚めるとreadyの値が変更され、プライマリメモリが更新されても卵用はありません.
次の例を見てみましょう.
package com.fsun.research.thread.violate;
public class MainTest {
private static boolean ready;
private static class CounterThread implements Runnable{
@Override
public void run() {
System.out.println("ready====="+ready);
try {
Thread.sleep(1000); // 1
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1 ready "+ready);
}
}
public static void main(String[] args) {
new Thread(new CounterThread()).start();
System.out.println(" 300 ");
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
ready=true;
}
}
マスタースレッドスリープ300 msマスタースレッドがreadyを更新する前に、CounterThreadがマスターメモリからreadyの値を読み出すことを保証するために.CounterThreadは、1秒間の睡眠後にreadyの値を読み出し、このときメインスレッド更新後の値を読み出す.プログラムの実行フローを制御可能にスレッドスリープを追加するために、実際にはテスト中にスレッドスリープを追加しないで、スレッドが短時間でreadyの値を頻繁に読み取らない限り、読み取ったreadyの値エラーが発生しない場合.
高同時性の場合、共有変数jvmでは、各スレッドが読み出す値が同じであることは保証されません.violateはこの時ちょうど役に立ちます.violateキーワードについては自分でグーグルしてください.