ホームページ  >  記事  >  Java  >  Javaにおけるvolatileキーワードの使い方と注意点

Javaにおけるvolatileキーワードの使い方と注意点

黄舟
黄舟オリジナル
2017-07-30 10:14:401616ブラウズ

この記事では、Java の volatile キーワードの使用に関する関連情報と注意事項を主に紹介します。変数が volatile として宣言されると、Java メモリ モデルにより、その変数を使用するすべてのスレッドが同じ一貫した値を参照できるようになります。 、必要な友達は、

java volatile キーワードの使用法と注意事項を参照してください

volatile キーワードとは

volatile キーワードは、マルチスレッド プログラムで非常に重要な役割を果たします。複数のスレッドが同じ変数を操作する場合、各スレッドはその変数のローカル キャッシュ コピーを持ちます。そのため、スレッドがこの変数の値を変更すると、実際にはローカル キャッシュ内の変数値が変更されます。メインメモリの場合、この変数を操作する他のスレッドは、この変数の値が変更されたことを認識しません。この状況を回避するには、この変数を volatile キーワードで宣言すると、変数はローカル キャッシュに保存されず、スレッドがその値を変更するときにメイン メモリに保存されます。更新された値はメイン メモリに更新され、他のスレッドが更新された値にアクセスできるようになります。変数が volatile として宣言されると、Java メモリ モデルにより、その変数を使用するすべてのスレッドが同じ一貫した値を参照するようになります。

volatile キーワードを使用します

まず、VolatileData クラスを作成します。コードは次のとおりです。


public class VolatileData {

  //声明为volatile类型
  private volatile int counter = 0;

  /**
  * 返回counter变量的值
  * @return
  */
  public int getCounter() {
    return counter;
  }

  /**
  * 自增counter变量的值
  */
  public void increaseCounter() {
    ++counter;
  }
}

次に、VolatileThread クラスを作成します。コードは次のとおりです。


public class VolatileThread extends Thread {
  private final VolatileData volatileData;

  public VolatileThread(VolatileData volatileData) {
    this.volatileData = volatileData;
  }

  /**
  * 调用VolatileData类中的两个方法,进行取值和自增操作
  */
  @Override
  public void run() {
    int oldValue = volatileData.getCounter();
    System.out.println("[Thread " + Thread.currentThread().getId() + "]: Old value = " + oldValue);
    volatileData.increaseCounter();
    int newValue = volatileData.getCounter();
    System.out.println("[Thread " + Thread.currentThread().getId() + "]: New value = " + newValue);
  }
 }

最後に、 VolatileMain クラスを作成し、上記のプログラム テストを実行すると、コードは次のようになります:


public class VolatileMain {

  private final static int TOTAL_THREADS = 2;

  public static void main(String[] args) throws InterruptedException {
    VolatileData volatileData = new VolatileData();

    Thread[] threads = new Thread[TOTAL_THREADS];
    for(int i = 0; i < TOTAL_THREADS; ++i)
      threads[i] = new VolatileThread(volatileData);

    //开始读取变量值的操作
    for(int i = 0; i < TOTAL_THREADS; ++i)
      threads[i].start();

    //等待所有线程操作终止
    for(int i = 0; i < TOTAL_THREADS; ++i)
      threads[i].join();
  }
}

VolatileMain クラスでは、2 つのスレッドを使用して volatile 変数にアクセスし、出力は次のようになります:


[Thread 10]: Old value = 0
[Thread 11]: Old value = 0
[Thread 10]: New value = 1
[Thread 11]: New value = 2

出力からわかるように、まず、両方のスレッドが同じ値を出力します。次に、increaseCounter メソッドが呼び出された後、両方のスレッドが最新の volatile 変数値にアクセスして出力します。

前発生関係

volatile キーワードを使用する場合、Java メモリ モデルの発生前関係について言及する必要があります。前発生関係は、Java のメモリ モデルの重要な側面です。これは 2 つの異なるイベントの間に構築され、最初のイベントによるオブジェクトへのすべての変更を 2 番目のイベントで確認して反映できるようにします。たとえば、あるスレッドが揮発性変数に書き込み、その後別のスレッドがその変数にアクセスすると、事前発生関係が確立されます。したがって、揮発性変数へのすべての変更は他のスレッドから認識されます。

注意事項

プログラムで volatile キーワードを使用する場合は、次の点に注意する必要があります:

  1. volatile キーワードは、メモリ整合性エラーによるアトム間の同期操作の必要性を排除するものではありません。まだ可能です

  2. アトミック変数の使用は、同期された同期コードを使用するより効率的ですが、メモリ整合性エラーを回避するには追加の努力が必要です

  3. volatileキーワードは、同期された同期コードブロックおよびメソッドの代替ではありません

以上がJavaにおけるvolatileキーワードの使い方と注意点の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。