Java の Atomic パッケージで使用されるコード共有の詳細な紹介
はじめに
Java は、JDK1.5 以降 java.util.concurrent.atomic パッケージを提供しています。これにより、プログラマがマルチスレッド環境でロックフリーのアトミック操作を実行できるようになります。アトミック変数の最下層はプロセッサによって提供されるアトミック命令を使用しますが、異なるCPUアーキテクチャは異なるアトミック命令を提供する可能性があり、また何らかの形式の内部ロックも必要とする場合があるため、このメソッドはスレッドがロックされないことを完全に保証することはできません。ブロックされる。
Atomic パッケージの紹介
Atomic パッケージには 12 のクラスと 4 つのアトミック更新メソッド、つまりアトミック更新基本タイプ、アトミック更新配列、アトミック更新参照、およびアトミック更新フィールドがあります。 Atomic パッケージ内のクラスは、基本的に Unsafe を使用して実装されたラッパー クラスです。
アトミック更新基本型クラス
は、基本型をアトミックに更新するために使用されます。 Atomic パッケージは、次の 3 つのクラスを提供します:
AtomicBoolean: アトミック更新ブール型。
AtomicInteger: アトミック更新整数。
AtomicLong: アトミック更新ロング。
AtomicInteger の一般的なメソッドは次のとおりです:
int addAndGet(int delta): 入力値をインスタンスの値 (AtomicInteger の値) にアトミックに加算し、結果を返します
boolean CompareAndSet(int Expect, int update) : 入力値が期待値と等しい場合、値を入力値に原子的に設定します。
int getAndIncrement(): 現在の値に原子的に 1 を加算します。 注: ここで返される値は、増分前の値です。
void LazySet(int newValue): 最終的には newValue に設定されますが、lazySet を使用して値を設定した後でも、他のスレッドは短期間で古い値を読み取ることができる可能性があります。
int getAndSet(int newValue): 値を原子的に newValue に設定し、古い値を返します。
AtomicInteger のサンプル コードは次のとおりです:
import java.util.concurrent.atomic.AtomicInteger; public class AtomicIntegerTest { static AtomicInteger ai = new AtomicInteger(1); public static void main(String[] args) { System.out.println(ai.getAndIncrement()); System.out.println(ai.get()); } }
Output
1 2
Dessert
Atomic パッケージは 3 つの基本タイプのアトミック更新を提供しますが、Java の基本タイプには char、float、double などが含まれます。そこで問題は、他の基本型をアトミックに更新するにはどうすればよいでしょうか? Atomic パッケージのクラスは基本的に Unsafe を使用して実装されています。Unsafe のソース コードを見てみましょう。AtomicBoolean のソース コードを見ると、Unsafe には 3 つの CAS メソッドしか提供されていないことがわかります。 Boolean を整数に変換し、compareAndSwapInt を使用して CAS を実行するため、double のアトミック更新も同様のアイデアを使用して実装できます。
配列のアトミック更新クラス
Atomic パッケージには、次の 3 つのクラスが用意されています。
AtomicIntegerArray: 整数配列内の要素のアトミック更新。
AtomicLongArray: 長整数配列内の要素をアトミックに更新します。
AtomicReferenceArray: 参照型配列内の要素をアトミックに更新します。
AtomicIntegerArray クラスは、主に配列内の整数を更新するアトミックな方法を提供します。その一般的なメソッドは次のとおりです
int addAndGet(int i, int delta): 入力値をインデックスの要素にアトミックに追加します。配列内の i を加算します。
boolean CompareAndSet(int i, int Expect, int update): 現在の値が期待値と等しい場合、配列位置 i の要素を更新値にアトミックに設定します。
サンプルコードは次のとおりです:
public class AtomicIntegerArrayTest { static int[] value = new int[] { 1, 2 }; static AtomicIntegerArray ai = new AtomicIntegerArray(value); public static void main(String[] args) { ai.getAndSet(0, 3); System.out.println(ai.get(0)); System.out.println(value[0]); } }
output
3 1
AtomicIntegerArray クラスそのため、AtomicIntegerArray が内部配列要素を変更する場合、変更が行われても、渡された配列は影響を受けません。 アトミック更新参照型
アトミック更新の基本型である AtomicInteger は、1 つの変数のみを更新できます。複数の変数をアトミックに更新したい場合は、このアトミック更新参照型が提供するクラスを使用する必要があります。 Atomic パッケージは、次の 3 つのクラスを提供します:
- AtomicReference: アトミック更新参照タイプ。
- AtomicReferenceFieldUpdater: 参照型のフィールドをアトミックに更新します。
- AtomicMarkableReference: マーク ビットを使用した参照型のアトミック更新。ブール値のフラグ ビットと参照型をアトミックに更新することができます。構築メソッドは AtomicMarkableReference(VInitialRef, booleanInitialMark) です
- AtomicReference の使用例コードは次のとおりです:
public class AtomicReferenceTest { public static AtomicReference<user> atomicUserRef = new AtomicReference</user><user>(); public static void main(String[] args) { User user = new User("conan", 15); atomicUserRef.set(user); User updateUser = new User("Shinichi", 17); atomicUserRef.compareAndSet(user, updateUser); System.out.println(atomicUserRef.get().getName()); System.out.println(atomicUserRef.get().getOld()); } static class User { private String name; private int old; public User(String name, int old) { this.name = name; this.old = old; } public String getName() { return name; } public int getOld() { return old; } } }
Output
Shinichi 17
Atomic update field class
特定のクラスの特定のフィールドのみが必要な場合は、アトミック更新フィールド クラスを使用する必要があります。Atomic パッケージには次の 3 つのクラスが用意されています:
- AtomicIntegerFieldUpdater: 整数フィールドをアトミックに更新するためのアップデーター。
- AtomicLongFieldUpdater: 長整数フィールドをアトミックに更新するためのアップデーター。
AtomicStampedReference:原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于原子的更数据和数据的版本号,可以解决使用CAS进行原子更新时,可能出现的ABA问题。
原子更新字段类都是抽象类,每次使用都时候必须使用静态方法newUpdater创建一个更新器。原子更新类的字段的必须使用public Volatile修饰符。AtomicIntegerFieldUpdater的例子代码如下:
public class AtomicIntegerFieldUpdaterTest { private static AtomicIntegerFieldUpdater<User> a = AtomicIntegerFieldUpdater .newUpdater(User.class, "old"); public static void main(String[] args) { User conan = new User("conan", 10); System.out.println(a.getAndIncrement(conan)); System.out.println(a.get(conan)); } public static class User { private String name; public volatile int old; public User(String name, int old) { this.name = name; this.old = old; } public String getName() { return name; } public int getOld() { return old; } } }
输出
10 11
以上がJava の Atomic パッケージで使用されるコード共有の詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











Java の乱数ジェネレーターのガイド。ここでは、Java の関数について例を挙げて説明し、2 つの異なるジェネレーターについて例を挙げて説明します。

Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

Java のアームストロング番号に関するガイド。ここでは、Java でのアームストロング数の概要とコードの一部について説明します。

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです
