cas是無鎖優(yōu)化,或者叫自旋。通過Atomic類來實(shí)現(xiàn)。
由于一些常見的操作,加鎖的情況特別多,所以java提供了這些類,內(nèi)部自帶了鎖,當(dāng)然這些鎖不是由synchronized來實(shí)現(xiàn)的,而是通過cas的操作實(shí)現(xiàn)的。
public class study04 {
????public static void main(String[] args) {
????????study04 study =new study04();
? ? ? ? List threads =new ArrayList<>();
? ? ? ? for (int i=0; i <10; i++){
????????????threads.add(new Thread(study :: m, "thread-"+i));
? ? ? ? }
????????threads.forEach(o -> o.start());
? ? ? ? threads.forEach(o -> {
????????????try {
????????????????o.join();
? ? ? ? ? ? }catch (InterruptedException e) {
????????????????e.printStackTrace();
? ? ? ? ? ? }
????????});
? ? ? ? System.out.println(study.count);
? ? }
????AtomicIntegercount =new AtomicInteger(0);
? ? void m(){
????????for (int i =0; i <10000; i ++){
????????count.incrementAndGet();
? ? ????}
????}
}
count.incrementAndGet()的內(nèi)部實(shí)現(xiàn):
public final int incrementAndGet() {
????return unsafe.getAndAddInt(this, valueOffset, 1) +1;
}
public final int getAndAddInt(Object var1, long var2, int var4) {
????int var5;
? ? do {
????????var5 =this.getIntVolatile(var1, var2);
? ? }while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
? ? return var5;
}
compareAndSwapInt:
cas(V, Expected, NewValue)
? ? if V == Expected
? ? ? ? V = NewValue
? ? ? ? otherwise try again or fail
V是要修改的值,Expected是期望值,NewValue是新值,如果要修改的值等于期望值,那么代表沒有其他線程修改過它,可以設(shè)定新值,否則代表有其他線程修改過值,那么cas要重新嘗試讀取期望值。cas操作是cpu原語級的,中間不允許被打斷,是原子性的。
CAS修改的如果是對象會(huì)導(dǎo)致ABA問題。線程A發(fā)現(xiàn)對象(Expected)的引用還是原來的引用,就允許修改,但其實(shí)該對象可能已經(jīng)被線程B修改過值并重新引用到原來的對象上,線程A無法發(fā)現(xiàn)。要解決ABA問題需要引入版本號,compare的時(shí)候連版本號一起比較。
CAS是通過Unsafe這個(gè)類來實(shí)現(xiàn)的。