ホームページ  >  記事  >  Java  >  cas 命令のロックフリー プログラミングを実装する Java の例

cas 命令のロックフリー プログラミングを実装する Java の例

黄舟
黄舟オリジナル
2017-09-15 11:07:211465ブラウズ

この記事では主に Java 言語での cas 命令のロックフリープログラミングの実装例を紹介します。必要な方はそれについて学ぶことができます。

関連コンテンツに初めて触れるときは、volatile キーワードを使用する必要があります。これにより、変数の可視性が保証され、読み取りと書き込みのアトミック操作の実装に使用できることがわかります。 。 。しかし、一部の複合操作を volatile で実装することは無力です。 。 。最も典型的なのはインクリメント演算とデクリメント演算です。 。 。 。

同時環境では、データの一貫性を達成する最も簡単な方法は、同時に 1 つのスレッドだけがデータを操作できるようにロックすることであることがわかっています。 。 。 。たとえば、カウンターは次の方法で実装できます:


public class Counter {
  private volatile int a = 0;
  public synchronized int incrAndGet(int number) {
    this.a += number;
    return a;
  } 
  public synchronized int get() {
    return a;
  }
}

属性 a への同期アクセスを保証するために、すべての操作を synchronized キーワードで変更します。 。 。これにより、確かに同時環境での一貫性を確保できますが、ロック、ロック オーバーヘッド、スレッド スケジューリングなどの使用により、プログラムのスケーラビリティが制限されるため、ロックを使用しない実装が多くあります。 。 。 。

実際、これらのロックフリーのメソッドはすべて、プロセッサによって提供されるいくつかの CAS (比較および切り替え) 命令を使用します。この CAS は具体的に何を行うのでしょうか? 次のメソッドを使用して、CAS によって表されるセマンティクスを説明できます。

public synchronized int compareAndSwap(int expect, int newValue) {
    int old = this.a;
    if (old == expect) {
      this.a = newValue;
    }
    return old;
  }

さて、コードを通して CAS のセマンティクスについてよく理解してください。現在、ほとんどのプロセッサがアトミック CAS 命令を実装しているようです。 。
さて、Java で CAS が使用される場所を見てみましょう。まず、AtomicInteger 型を見てみましょう。これは同時実行ライブラリで提供される型です。これは内部定義であり、使用される属性です。値を保存するため、揮発性型であるため、スレッド間の可視性と読み書きのアトミック性を確保できます。 。 。

次に、より一般的に使用されるメソッドをいくつか見てみましょう:


private volatile int value;

このメソッドの機能は、現在の値にデルタを追加することです。ここでは、メソッド全体にロックがないことがわかります。実際にコード Javaでロックフリーカウンタを実装するメソッドであっても、ここでのcompareAndSetメソッドは以下のように定義されています。実際、JVM がプロセッサ自体の CAS 命令を呼び出してアトミックな操作を実装していることが推測できるはずです。 。 。


基本的に、AtomicInteger 型の重要なメソッドはロックフリーの方法で実装されます。 。したがって、同時環境では、このタイプを使用するとパフォーマンスが向上する可能性があります。 。 。

以上で、Java でロックフリー カウンターを実装することが完了しました。次に、ロックフリー スタックを実装し、コードを直接貼り付ける方法を見てみましょう。コードは、「JAVA Concurrent Programming Practice」から模倣されています。


public final int addAndGet(int delta) {
  for (;;) {
    int current = get();
    int next = current + delta;
    if (compareAndSet(current, next))
      return next;
  }
}

さて、上記のコードはロックフリーのスタックを実装しています。簡単です。 。 。同時環境では、ロックフリーのデータ構造は、ロックよりもはるかに優れた拡張性を実現できます。 。 。

ロックフリー プログラミングについて話すときは、ロックフリー キューについて言及する必要があります。実際、ロックフリー キューの実装は ConcurrentLinkedQueue で提供されています。その重要なメソッドの実装を見てみましょう。


public final boolean compareAndSet(int expect, int update) {
  return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

このメソッドは、キューの最後に要素を追加するために使用されます。ここでは、特定のロックフリー アルゴリズムについては、Michael-Scott によって提案されたノンブロッキング リンク リスト リンク アルゴリズムが使用されていることがわかります。使用済み。 。 。具体的にどのように機能するかを確認するには、「Java Concurrent Programming in Practice」でさらに詳しい概要をご覧ください。


さらに、他のメソッドも実際にはロックフリーの方法で実装されています。

最後に、実際のプログラミングでは、これらのロックフリー実装を同時環境で使用する方が良いです。結局のところ、その方がスケーラビリティが優れています。


概要


以上がcas 命令のロックフリー プログラミングを実装する Java の例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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