2.3.4非原子の特性
2443 ワード
キーワードvolatileは、インスタンス変数の複数のスレッド間の可視性を増加させるが、同期性を備えず、原子性を備えない.
プログラムの実行結果は次のとおりです.
カスタムスレッドクラスを変更します.JAvaファイルは次のとおりです.
プログラムの実行効果は次のとおりです.
上記のコードではprivate static void addCount()を使用する前にsynchronized同期キーワードを追加すると、volatileキーワードを使用してcount変数を宣言する必要はありません.
キーワードvolatileの主な使用場面は、複数のスレッドでインスタンス変数が変更されたことを感知し、最新の値を得ることができます.つまり、共有変数をマルチスレッドで読み出すことで、最新の値を得ることができます.
キーワードvolatileプロンプトスレッドは、あるメモリからではなく共有メモリから変数を読み出すたびに、同期データの可視性を保証します.しかし、ここで注意すべきは、i+、すなわちi=i+1のようなインスタンス変数のデータを変更すると、このような動作は原子操作ではないことである.つまり、非スレッドは安全です.式i++の操作手順は次のように分解されます.メモリからiの値 を取り出す. i計算iの値 iの値をメモリに と書きます.
2ステップ目に値を計算するときに、別のスレッドもiの値を変更すると、このとき汚れたデータが表示されます.解決策はsynchronizedキーワードを用いることであり,この知識点は前述の例で紹介した.だからvolatile自体はデータの原子性を処理するのではなく、データの読み書きを強制してメインメモリにタイムリーに影響を与える.
volatileで修飾された変数の場合、JVM仮想マシンは、プライマリメモリからスレッドワークメモリにロードされた値が最新であることを保証するだけです.volatileキーワードは、変数の読み取り時の可視性の問題を解決しますが、原子性を保証することはできません.複数のスレッドで同じインスタンス変数にアクセスするには、同期をロックする必要があります.
Javaマルチスレッドコアプログラミング技術から抜粋-2.3.4
/**
* MyThread
* @author wuyoushan
* @date 2017/3/21.
*/
public class MyThread extends Thread {
volatile public static int count;
private static void addCount(){
for (int i = 0; i < 100; i++) {
count++;
}
System.out.println("count="+count);
}
@Override
public void run() {
addCount();
}
}
/**
* @author wuyoushan
* @date 2017/3/20.
*/
public class Run {
public static void main(String[] args){
MyThread[] mythreadArray=new MyThread[100];
for (int i = 0; i < 100; i++) {
mythreadArray[i]=new MyThread();
}
for (int i = 0; i < 100; i++) {
mythreadArray[i].start();
}
}
}
プログラムの実行結果は次のとおりです.
count=3400
count=3500
count=3600
count=9900
count=9900
count=9900
カスタムスレッドクラスを変更します.JAvaファイルは次のとおりです.
/**
* MyThread
* @author wuyoushan
* @date 2017/3/21.
*/
public class MyThread extends Thread {
volatile public static int count;
// static
// synchronized static MyThread.class
// static , ,
//
synchronized private static void addCount(){
for (int i = 0; i < 100; i++) {
count++;
}
System.out.println("count="+count);
}
@Override
public void run() {
addCount();
}
}
プログラムの実行効果は次のとおりです.
count=9600
count=9700
count=9800
count=9900
count=10000
上記のコードではprivate static void addCount()を使用する前にsynchronized同期キーワードを追加すると、volatileキーワードを使用してcount変数を宣言する必要はありません.
キーワードvolatileの主な使用場面は、複数のスレッドでインスタンス変数が変更されたことを感知し、最新の値を得ることができます.つまり、共有変数をマルチスレッドで読み出すことで、最新の値を得ることができます.
キーワードvolatileプロンプトスレッドは、あるメモリからではなく共有メモリから変数を読み出すたびに、同期データの可視性を保証します.しかし、ここで注意すべきは、i+、すなわちi=i+1のようなインスタンス変数のデータを変更すると、このような動作は原子操作ではないことである.つまり、非スレッドは安全です.式i++の操作手順は次のように分解されます.
2ステップ目に値を計算するときに、別のスレッドもiの値を変更すると、このとき汚れたデータが表示されます.解決策はsynchronizedキーワードを用いることであり,この知識点は前述の例で紹介した.だからvolatile自体はデータの原子性を処理するのではなく、データの読み書きを強制してメインメモリにタイムリーに影響を与える.
volatileで修飾された変数の場合、JVM仮想マシンは、プライマリメモリからスレッドワークメモリにロードされた値が最新であることを保証するだけです.volatileキーワードは、変数の読み取り時の可視性の問題を解決しますが、原子性を保証することはできません.複数のスレッドで同じインスタンス変数にアクセスするには、同期をロックする必要があります.
Javaマルチスレッドコアプログラミング技術から抜粋-2.3.4