無鎖
通過CAS+volatile來實現
while (true) {
int prev = balance.get();
int next = prev - amount;
if (balance.compareAndSet(prev, next)) {
break;
}
}
// 可以簡化為下面的方法
// balance.addAndGet(-1 * amount);
CAS特點
- 基于樂觀鎖設計,不怕修改共享變量,修改了也沒事,繼續(xù)等待就可以。
- synchronized是基于悲觀鎖,鎖住操作,會導致線程狀態(tài)切換,也會用戶態(tài)到內核態(tài)切換。效率較差。
- CAS需要重試,CPU空轉,如果是單核cpu或者線程數量大于cpu核心數,也會導致線程狀態(tài)一直切換,效率反而變低。
CAS+volatile
cas+volatitle組合實現樂觀鎖,volatile只能保證可見性,和一部分的有序性,并不能防止指令重排序。通過cas+volatitle的組合實現樂觀鎖。
JUC中的原子類
原子整數
基本的i++,i--,等操作,還可以是表達式,表達式可以保證是原子操作。
AtomicBoolean
AtomicInteger
AtomicLong
原子引用
通過無鎖的方式更新變量對象的引用值。
AtomicReference//不能解決ABA問題
AtomicStampedReference//增加版本號,可以追蹤每次修改
AtomicMarkableReference//增加標識,可以看到是否修改,但不追蹤整個過程
原子數組
AtomicIntegerArray
AtomicLongArray
AtomicReferenceArray
字段更新器
線程安全的方式更新對象中的某個字段
需要配合volatitle使用:字段必須是volatile修飾的,否則拋出異常
AtomicReferenceFieldUpdater
AtomicIntegerFieldUpdater
AtomicLongFieldUpdater
原子累加器
性能更好
Unsafe
Unsafe 對象提供了非常底層的,操作內存、線程的方法,Unsafe 對象不能直接調用,只能通過反射獲得
Unsafe實現CAS
class Student {
volatile int id;
volatile String name; }
Unsafe unsafe = UnsafeAccessor.getUnsafe();
Field id = Student.class.getDeclaredField("id");
Field name = Student.class.getDeclaredField("name");
// 獲得成員變量的偏移量
long idOffset = UnsafeAccessor.unsafe.objectFieldOffset(id);
long nameOffset = UnsafeAccessor.unsafe.objectFieldOffset(name);
Student student = new Student();
// 使用 cas 方法替換成員變量的值
UnsafeAccessor.unsafe.compareAndSwapInt(student, idOffset, 0, 20); // 返回 true
UnsafeAccessor.unsafe.compareAndSwapObject(student, nameOffset, null, "張三"); // 返回 true
System.out.println(student);