ç¹å»å
³æ³¨[å
¬ä¼å·](#å
¬ä¼å·)åæ¶è·åç¬ä¸»ææ°æ´æ°æç« ï¼å¹¶å¯å
è´¹é¢åæ¬ææ¡£é
å¥çãJavaé¢è¯çªå»ã以åJavaå·¥ç¨å¸å¿
å¤å¦ä¹ èµæºã
> 个人è§å¾è¿ä¸èææ¡åºæ¬ç使ç¨å³å¯ï¼
- [1 Atomic ååç±»ä»ç»](#1-atomic-ååç±»ä»ç»)
- [2 åºæ¬ç±»åååç±»](#2-åºæ¬ç±»åååç±»)
- [2.1 åºæ¬ç±»åååç±»ä»ç»](#21-åºæ¬ç±»åååç±»ä»ç»)
- [2.2 AtomicInteger å¸¸è§æ¹æ³ä½¿ç¨](#22-atomicinteger-å¸¸è§æ¹æ³ä½¿ç¨)
- [2.3 åºæ¬æ°æ®ç±»åååç±»çä¼å¿](#23-åºæ¬æ°æ®ç±»åååç±»çä¼å¿)
- [2.4 AtomicInteger 线ç¨å®å
¨åçç®ååæ](#24-atomicinteger-线ç¨å®å
¨åçç®ååæ)
- [3 æ°ç»ç±»åååç±»](#3-æ°ç»ç±»åååç±»)
- [3.1 æ°ç»ç±»åååç±»ä»ç»](#31-æ°ç»ç±»åååç±»ä»ç»)
- [3.2 AtomicIntegerArray å¸¸è§æ¹æ³ä½¿ç¨](#32-atomicintegerarray-å¸¸è§æ¹æ³ä½¿ç¨)
- [4 å¼ç¨ç±»åååç±»](#4-å¼ç¨ç±»åååç±»)
- [4.1 å¼ç¨ç±»åååç±»ä»ç»](#41--å¼ç¨ç±»åååç±»ä»ç»)
- [4.2 AtomicReference 类使ç¨ç¤ºä¾](#42-atomicreference-类使ç¨ç¤ºä¾)
- [4.3 AtomicStampedReference 类使ç¨ç¤ºä¾](#43-atomicstampedreference-类使ç¨ç¤ºä¾)
- [4.4 AtomicMarkableReference 类使ç¨ç¤ºä¾](#44-atomicmarkablereference-类使ç¨ç¤ºä¾)
- [5 对象ç屿§ä¿®æ¹ç±»åååç±»](#5-对象ç屿§ä¿®æ¹ç±»åååç±»)
- [5.1 对象ç屿§ä¿®æ¹ç±»åååç±»ä»ç»](#51-对象ç屿§ä¿®æ¹ç±»åååç±»ä»ç»)
- [5.2 AtomicIntegerFieldUpdater 类使ç¨ç¤ºä¾](#52-atomicintegerfieldupdater-类使ç¨ç¤ºä¾)
### 1 Atomic ååç±»ä»ç»
Atomic ç¿»è¯æä¸ææ¯ååçææãå¨åå¦ä¸ï¼æä»¬ç¥éå忝ææä¸è¬ç©è´¨çæå°åä½ï¼å¨åå¦ååºä¸æ¯ä¸å¯åå²çã卿们è¿é Atomic æ¯æä¸ä¸ªæä½æ¯ä¸å¯ä¸æçãå³ä½¿æ¯å¨å¤ä¸ªçº¿ç¨ä¸èµ·æ§è¡çæ¶åï¼ä¸ä¸ªæä½ä¸æ¦å¼å§ï¼å°±ä¸ä¼è¢«å
¶ä»çº¿ç¨å¹²æ°ã
æä»¥ï¼æè°åå类说ç®åç¹å°±æ¯å
·æåå/ååæä½ç¹å¾çç±»ã
å¹¶åå
`java.util.concurrent` çååç±»é½åæ¾å¨`java.util.concurrent.atomic`ä¸,å¦ä¸å¾æç¤ºã

æ ¹æ®æä½çæ°æ®ç±»åï¼å¯ä»¥å°JUCå
ä¸çååç±»å为4ç±»
**åºæ¬ç±»å**
使ç¨ååçæ¹å¼æ´æ°åºæ¬ç±»å
- AtomicIntegerï¼æ´åååç±»
- AtomicLongï¼é¿æ´åååç±»
- AtomicBoolean ï¼å¸å°åååç±»
**æ°ç»ç±»å**
使ç¨ååçæ¹å¼æ´æ°æ°ç»éçæä¸ªå
ç´
- AtomicIntegerArrayï¼æ´åæ°ç»ååç±»
- AtomicLongArrayï¼é¿æ´åæ°ç»ååç±»
- AtomicReferenceArray ï¼å¼ç¨ç±»åæ°ç»ååç±»
**å¼ç¨ç±»å**
- AtomicReferenceï¼å¼ç¨ç±»åååç±»
- AtomicMarkableReferenceï¼ååæ´æ°å¸¦ææ è®°çå¼ç¨ç±»åãè¯¥ç±»å° boolean æ è®°ä¸å¼ç¨å
³èèµ·æ¥ï¼~~ä¹å¯ä»¥è§£å³ä½¿ç¨ CAS è¿è¡ååæ´æ°æ¶å¯è½åºç°ç ABA é®é¢ã~~
- AtomicStampedReference ï¼ååæ´æ°å¸¦æçæ¬å·çå¼ç¨ç±»åãè¯¥ç±»å°æ´æ°å¼ä¸å¼ç¨å
³èèµ·æ¥ï¼å¯ç¨äºè§£å³ååçæ´æ°æ°æ®åæ°æ®ççæ¬å·ï¼å¯ä»¥è§£å³ä½¿ç¨ CAS è¿è¡ååæ´æ°æ¶å¯è½åºç°ç ABA é®é¢ã
**对象ç屿§ä¿®æ¹ç±»å**
- AtomicIntegerFieldUpdater:ååæ´æ°æ´ååæ®µçæ´æ°å¨
- AtomicLongFieldUpdaterï¼ååæ´æ°é¿æ´ååæ®µçæ´æ°å¨
- AtomicReferenceFieldUpdaterï¼ååæ´æ°å¼ç¨ç±»åéçåæ®µ
> ä¿®æ£: **AtomicMarkableReference ä¸è½è§£å³ABAé®é¢** **[issue#626](https://github.com/Snailclimb/JavaGuide/issues/626)**
```java
/**
AtomicMarkableReferenceæ¯å°ä¸ä¸ªbooleanå¼ä½æ¯å¦ææ´æ¹çæ è®°ï¼æ¬è´¨å°±æ¯å®ççæ¬å·åªæä¸¤ä¸ªï¼trueåfalseï¼
ä¿®æ¹çæ¶åå¨è¿ä¸¤ä¸ªçæ¬å·ä¹é´æ¥å忢ï¼è¿æ ·åå¹¶ä¸è½è§£å³ABAçé®é¢ï¼åªæ¯ä¼éä½ABAé®é¢åççå çèå·²
@author : mazh
@Date : 2020/1/17 14:41
*/
public class SolveABAByAtomicMarkableReference {
private static AtomicMarkableReference atomicMarkableReference = new AtomicMarkableReference(100, false);
public static void main(String[] args) {
Thread refT1 = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
atomicMarkableReference.compareAndSet(100, 101, atomicMarkableReference.isMarked(), !atomicMarkableReference.isMarked());
atomicMarkableReference.compareAndSet(101, 100, atomicMarkableReference.isMarked(), !atomicMarkableReference.isMarked());
});
Thread refT2 = new Thread(() -> {
boolean marked = atomicMarkableReference.isMarked();
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
boolean c3 = atomicMarkableReference.compareAndSet(100, 101, marked, !marked);
System.out.println(c3); // è¿åtrue,å®é
åºè¯¥è¿åfalse
});
refT1.start();
refT2.start();
}
}
```
**CAS ABA é®é¢**
- æè¿°: 第ä¸ä¸ªçº¿ç¨åå°äºåé x çå¼ Aï¼ç¶åå·´æå·´æå¹²å«çäºï¼æ»ä¹å°±æ¯åªæ¿å°äºåé x çå¼ Aãè¿æ®µæ¶é´å
第äºä¸ªçº¿ç¨ä¹åå°äºåé x çå¼ Aï¼ç¶åæåé x ç弿¹ä¸º Bï¼ç¶åå·´æå·´æå¹²å«çäºï¼æååæåé x çå¼å为 A ï¼ç¸å½äºè¿åäºï¼ãå¨è¿ä¹å第ä¸ä¸ªçº¿ç¨ç»äºè¿è¡äºåé x çæä½ï¼ä½æ¯æ¤æ¶åé x çå¼è¿æ¯ Aï¼æä»¥ compareAndSet æä½æ¯æåã
- ä¾åæè¿°(å¯è½ä¸å¤ªåéï¼ä½å¥½çè§£): å¹´åï¼ç°é为é¶ï¼ç¶åéè¿æ£å¸¸å³å¨èµäºä¸ç¾ä¸ï¼ä¹åæ£å¸¸æ¶è´¹äºï¼æ¯å¦ä¹°æ¿åï¼ä¸ç¾ä¸ãå¹´æ«ï¼è½ç¶ç°éé¶æ¶å
¥ï¼å¯è½åæå
¶ä»å½¢å¼äºï¼ï¼ä½æ¯èµäºé±æ¯äºå®ï¼è¿æ¯å¾äº¤ç¨çï¼
- 代ç ä¾åï¼ä»¥``` AtomicInteger ```为ä¾ï¼
```java
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicIntegerDefectDemo {
public static void main(String[] args) {
defectOfABA();
}
static void defectOfABA() {
final AtomicInteger atomicInteger = new AtomicInteger(1);
Thread coreThread = new Thread(
() -> {
final int currentValue = atomicInteger.get();
System.out.println(Thread.currentThread().getName() + " ------ currentValue=" + currentValue);
// è¿æ®µç®çï¼æ¨¡æå¤çå
¶ä»ä¸å¡è±è´¹çæ¶é´
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
boolean casResult = atomicInteger.compareAndSet(1, 2);
System.out.println(Thread.currentThread().getName()
+ " ------ currentValue=" + currentValue
+ ", finalValue=" + atomicInteger.get()
+ ", compareAndSet Result=" + casResult);
}
);
coreThread.start();
// è¿æ®µç®çï¼ä¸ºäºè®© coreThread 线ç¨å
è·èµ·æ¥
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread amateurThread = new Thread(
() -> {
int currentValue = atomicInteger.get();
boolean casResult = atomicInteger.compareAndSet(1, 2);
System.out.println(Thread.currentThread().getName()
+ " ------ currentValue=" + currentValue
+ ", finalValue=" + atomicInteger.get()
+ ", compareAndSet Result=" + casResult);
currentValue = atomicInteger.get();
casResult = atomicInteger.compareAndSet(2, 1);
System.out.println(Thread.currentThread().getName()
+ " ------ currentValue=" + currentValue
+ ", finalValue=" + atomicInteger.get()
+ ", compareAndSet Result=" + casResult);
}
);
amateurThread.start();
}
}
```
è¾åºå
容å¦ä¸ï¼
```
Thread-0 ------ currentValue=1
Thread-1 ------ currentValue=1, finalValue=2, compareAndSet Result=true
Thread-1 ------ currentValue=2, finalValue=1, compareAndSet Result=true
Thread-0 ------ currentValue=1, finalValue=2, compareAndSet Result=true
```
ä¸é¢æä»¬æ¥è¯¦ç»ä»ç»ä¸ä¸è¿äºååç±»ã
### 2 åºæ¬ç±»åååç±»
#### 2.1 åºæ¬ç±»åååç±»ä»ç»
使ç¨ååçæ¹å¼æ´æ°åºæ¬ç±»å
- AtomicIntegerï¼æ´åååç±»
- AtomicLongï¼é¿æ´åååç±»
- AtomicBoolean ï¼å¸å°åååç±»
ä¸é¢ä¸ä¸ªç±»æä¾çæ¹æ³å ä¹ç¸åï¼æä»¥æä»¬è¿é以 AtomicInteger 为ä¾åæ¥ä»ç»ã
**AtomicInteger ç±»å¸¸ç¨æ¹æ³**
```java
public final int get() //è·åå½åçå¼
public final int getAndSet(int newValue)//è·åå½åçå¼ï¼å¹¶è®¾ç½®æ°çå¼
public final int getAndIncrement()//è·åå½åçå¼ï¼å¹¶èªå¢
public final int getAndDecrement() //è·åå½åçå¼ï¼å¹¶èªå
public final int getAndAdd(int delta) //è·åå½åçå¼ï¼å¹¶å ä¸é¢æçå¼
boolean compareAndSet(int expect, int update) //妿è¾å
¥çæ°å¼çäºé¢æå¼ï¼å以ååæ¹å¼å°è¯¥å¼è®¾ç½®ä¸ºè¾å
¥å¼ï¼updateï¼
public final void lazySet(int newValue)//æç»è®¾ç½®ä¸ºnewValue,ä½¿ç¨ lazySet 设置ä¹åå¯è½å¯¼è´å
¶ä»çº¿ç¨å¨ä¹åçä¸å°æ®µæ¶é´å
è¿æ¯å¯ä»¥è¯»å°æ§çå¼ã
```
#### 2.2 AtomicInteger å¸¸è§æ¹æ³ä½¿ç¨
```java
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicIntegerTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
int temvalue = 0;
AtomicInteger i = new AtomicInteger(0);
temvalue = i.getAndSet(3);
System.out.println("temvalue:" + temvalue + "; i:" + i);//temvalue:0; i:3
temvalue = i.getAndIncrement();
System.out.println("temvalue:" + temvalue + "; i:" + i);//temvalue:3; i:4
temvalue = i.getAndAdd(5);
System.out.println("temvalue:" + temvalue + "; i:" + i);//temvalue:4; i:9
}
}
```
#### 2.3 åºæ¬æ°æ®ç±»åååç±»çä¼å¿
éè¿ä¸ä¸ªç®åä¾å带大家çä¸ä¸åºæ¬æ°æ®ç±»åååç±»çä¼å¿
**â å¤çº¿ç¨ç¯å¢ä¸ä½¿ç¨ååç±»ä¿è¯çº¿ç¨å®å
¨ï¼åºæ¬æ°æ®ç±»åï¼**
```java
class Test {
private volatile int count = 0;
//è¥è¦çº¿ç¨å®å
¨æ§è¡æ§è¡count++ï¼éè¦å é
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
```
**â¡å¤çº¿ç¨ç¯å¢ä½¿ç¨ååç±»ä¿è¯çº¿ç¨å®å
¨ï¼åºæ¬æ°æ®ç±»åï¼**
```java
class Test2 {
private AtomicInteger count = new AtomicInteger();
public void increment() {
count.incrementAndGet();
}
//使ç¨AtomicIntegerä¹åï¼ä¸éè¦å éï¼ä¹å¯ä»¥å®ç°çº¿ç¨å®å
¨ã
public int getCount() {
return count.get();
}
}
```
#### 2.4 AtomicInteger 线ç¨å®å
¨åçç®ååæ
AtomicInteger ç±»çé¨åæºç ï¼
```java
// setup to use Unsafe.compareAndSwapInt for updatesï¼æ´æ°æä½æ¶æä¾âæ¯è¾å¹¶æ¿æ¢âçä½ç¨ï¼
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
private volatile int value;
```
AtomicInteger 类主è¦å©ç¨ CAS (compare and swap) + volatile å native æ¹æ³æ¥ä¿è¯ååæä½ï¼ä»èé¿å
synchronized çé«å¼éï¼æ§è¡æç大为æåã
CASçåçæ¯æ¿ææçå¼å忬çä¸ä¸ªå¼ä½æ¯è¾ï¼å¦æç¸ååæ´æ°ææ°çå¼ãUnSafe ç±»ç objectFieldOffset() æ¹æ³æ¯ä¸ä¸ªæ¬å°æ¹æ³ï¼è¿ä¸ªæ¹æ³æ¯ç¨æ¥æ¿å°â忥çå¼âçå
åå°åãå¦å¤ value æ¯ä¸ä¸ªvolatileåéï¼å¨å
åä¸å¯è§ï¼å æ¤ JVM å¯ä»¥ä¿è¯ä»»ä½æ¶å»ä»»ä½çº¿ç¨æ»è½æ¿å°è¯¥åéçææ°å¼ã
### 3 æ°ç»ç±»åååç±»
#### 3.1 æ°ç»ç±»åååç±»ä»ç»
使ç¨ååçæ¹å¼æ´æ°æ°ç»éçæä¸ªå
ç´
- AtomicIntegerArrayï¼æ´å½¢æ°ç»ååç±»
- AtomicLongArrayï¼é¿æ´å½¢æ°ç»ååç±»
- AtomicReferenceArray ï¼å¼ç¨ç±»åæ°ç»ååç±»
ä¸é¢ä¸ä¸ªç±»æä¾çæ¹æ³å ä¹ç¸åï¼æä»¥æä»¬è¿é以 AtomicIntegerArray 为ä¾åæ¥ä»ç»ã
**AtomicIntegerArray ç±»å¸¸ç¨æ¹æ³**
```java
public final int get(int i) //è·å index=i ä½ç½®å
ç´ çå¼
public final int getAndSet(int i, int newValue)//è¿å index=i ä½ç½®çå½åçå¼ï¼å¹¶å°å
¶è®¾ç½®ä¸ºæ°å¼ï¼newValue
public final int getAndIncrement(int i)//è·å index=i ä½ç½®å
ç´ çå¼ï¼å¹¶è®©è¯¥ä½ç½®çå
ç´ èªå¢
public final int getAndDecrement(int i) //è·å index=i ä½ç½®å
ç´ çå¼ï¼å¹¶è®©è¯¥ä½ç½®çå
ç´ èªå
public final int getAndAdd(int i, int delta) //è·å index=i ä½ç½®å
ç´ çå¼ï¼å¹¶å ä¸é¢æçå¼
boolean compareAndSet(int i, int expect, int update) //妿è¾å
¥çæ°å¼çäºé¢æå¼ï¼å以ååæ¹å¼å° index=i ä½ç½®çå
ç´ å¼è®¾ç½®ä¸ºè¾å
¥å¼ï¼updateï¼
public final void lazySet(int i, int newValue)//æç» å°index=i ä½ç½®çå
ç´ è®¾ç½®ä¸ºnewValue,ä½¿ç¨ lazySet 设置ä¹åå¯è½å¯¼è´å
¶ä»çº¿ç¨å¨ä¹åçä¸å°æ®µæ¶é´å
è¿æ¯å¯ä»¥è¯»å°æ§çå¼ã
```
#### 3.2 AtomicIntegerArray å¸¸è§æ¹æ³ä½¿ç¨
```java
import java.util.concurrent.atomic.AtomicIntegerArray;
public class AtomicIntegerArrayTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
int temvalue = 0;
int[] nums = { 1, 2, 3, 4, 5, 6 };
AtomicIntegerArray i = new AtomicIntegerArray(nums);
for (int j = 0; j < nums.length; j++) {
System.out.println(i.get(j));
}
temvalue = i.getAndSet(0, 2);
System.out.println("temvalue:" + temvalue + "; i:" + i);
temvalue = i.getAndIncrement(0);
System.out.println("temvalue:" + temvalue + "; i:" + i);
temvalue = i.getAndAdd(0, 5);
System.out.println("temvalue:" + temvalue + "; i:" + i);
}
}
```
### 4 å¼ç¨ç±»åååç±»
#### 4.1 å¼ç¨ç±»åååç±»ä»ç»
åºæ¬ç±»åååç±»åªè½æ´æ°ä¸ä¸ªåéï¼å¦æéè¦ååæ´æ°å¤ä¸ªåéï¼éè¦ä½¿ç¨ å¼ç¨ç±»åååç±»ã
- AtomicReferenceï¼å¼ç¨ç±»åååç±»
- AtomicStampedReferenceï¼ååæ´æ°å¸¦æçæ¬å·çå¼ç¨ç±»åãè¯¥ç±»å°æ´æ°å¼ä¸å¼ç¨å
³èèµ·æ¥ï¼å¯ç¨äºè§£å³ååçæ´æ°æ°æ®åæ°æ®ççæ¬å·ï¼å¯ä»¥è§£å³ä½¿ç¨ CAS è¿è¡ååæ´æ°æ¶å¯è½åºç°ç ABA é®é¢ã
- AtomicMarkableReference ï¼ååæ´æ°å¸¦ææ è®°çå¼ç¨ç±»åãè¯¥ç±»å° boolean æ è®°ä¸å¼ç¨å
³èèµ·æ¥ï¼~~ä¹å¯ä»¥è§£å³ä½¿ç¨ CAS è¿è¡ååæ´æ°æ¶å¯è½åºç°ç ABA é®é¢ã~~
ä¸é¢ä¸ä¸ªç±»æä¾çæ¹æ³å ä¹ç¸åï¼æä»¥æä»¬è¿é以 AtomicReference 为ä¾åæ¥ä»ç»ã
#### 4.2 AtomicReference 类使ç¨ç¤ºä¾
```java
import java.util.concurrent.atomic.AtomicReference;
public class AtomicReferenceTest {
public static void main(String[] args) {
AtomicReference