java原子操作cas_java并发编程系列二:原子操作/CAS
什么是原子操作
不可被中斷的一個或者一系列操作
實現(xiàn)原子操作的方式
Java可以通過鎖和循環(huán)CAS的方式實現(xiàn)原子操作
CAS(?Compare And Swap?) ?為什么要有CAS?
Compare And Swap就是比較并且交換的一個原子操作,由Cpu在指令級別上進行保證。
為什么要有CAS:因為通過鎖實現(xiàn)原子操作時,其他線程必須等待已經(jīng)獲得鎖的線程運行完以后才能獲得資源,這樣就會占用系統(tǒng)的大量資源
CAS包含哪些參數(shù)?
CAS包含三個參數(shù):1、變量所在內(nèi)存地址V;2、變量對應的值A;3、我們將要修改的值B。如果說V上的變量的值是A的話,就用B重新賦值,如果不是A,那就什么事也不做,操作的返回結(jié)果原值是多少。
循環(huán)CAS:在一個(死)循環(huán)【for(;;)】里不斷進行CAS操作,直到成功為止(自旋操作即死循環(huán))。
CAS實現(xiàn)原子操作的三大問題
1、?ABA問題:其他的線程把值改成了B,很快改成了A,原子操作的線程發(fā)現(xiàn)值是A就修改,這樣會有問題。解決ABA,引入版本號:1A-》2C-》3A
2、?循環(huán)時間很長的話,cpu的負荷比較大
3、?對一個變量進行操作可以,同時操作多個共享變量有點麻煩
CAS線程安全(面試點)
通過硬件層面的阻塞實現(xiàn)原子操作的安全
原子更新基本類型類
AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference。
AtomicInteger的常用方法如下
·int addAndGet(int delta):
·boolean compareAndSet(int expect,int update):
·int getAndIncrement():?原子遞增,但是返回的是自增以前的值
incrementAndGet原子遞增,但是返回的是自增以后的值
·int getAndSet(int newValue):
packagecom.lgs.atomicint;importjava.util.concurrent.atomic.AtomicInteger;/*** lgs
* 原子操作更新整型*/
public classAtomicIntTest {static AtomicInteger ai = new AtomicInteger(1);public static voidmain(String[] args) {
System.out.println(ai.getAndIncrement());
ai.incrementAndGet();
System.out.println(ai.get());
}
}
輸出:
1
3
原子更新數(shù)組類
AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray
AtomicIntegerArray類主要是提供原子的方式更新數(shù)組里的整型,
其常用方法如下。
·int addAndGet(int i,int delta):
·boolean compareAndSet(int i,int expect,int update):
數(shù)組通過構造方法傳入,類會將數(shù)組復制一份,原數(shù)組不會發(fā)生變化。
packagecom.lgs.atomicarray;importjava.util.concurrent.atomic.AtomicIntegerArray;/*** lgs
* 原子操作更新數(shù)組*/
public classAtomicArray {static int[] value = new int[]{1,2};static AtomicIntegerArray ai = newAtomicIntegerArray(value);public static voidmain(String[] args) {
ai.getAndSet(0,3);
System.out.println(ai.get(0));
System.out.println(value[0]);
}
}
輸出:
3
1
原子更新引用類型提供的類。
·AtomicReference: 可以解決更新多個變量的問題
·AtomicStampedReference:解決ABA問題?使用數(shù)字作為版本 關心得是有幾個人改過
·AtomicMarkableReference:解決ABA問題?使用Boolean作為版本,關心的是有沒有修改過
packagecom.lgs;importjava.util.concurrent.atomic.AtomicReference;/*** lgs
* 原子操作更新引用類型即可以同時更新多個值*/
public classAtomicRef {static AtomicReference userAtomicReference = new AtomicReference<>();public static voidmain(String[] args) {
User user= new User("lgs",26);
userAtomicReference.set(user);
User updateUser= new User("ll",27);
userAtomicReference.compareAndSet(user,updateUser);
System.out.println(userAtomicReference.get().getName());
System.out.println(userAtomicReference.get().getOld());
}static classUser{privateString name;private intold;public User(String name, intold) {this.name =name;this.old =old;
}publicString getName() {returnname;
}public intgetOld() {returnold;
}
}
}
輸出:
ll
27
原子更新字段類
Atomic包提供了以下3個類進行原子字段更新。
·AtomicReferenceFieldUpdater:
·AtomicIntegerFieldUpdater:
·AtomicLongFieldUpdater:
違反了面向?qū)ο蟮脑瓌t,一般不使用
總結(jié)
以上是生活随笔為你收集整理的java原子操作cas_java并发编程系列二:原子操作/CAS的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 国产大飞机C919订单数超1200架 计
- 下一篇: 好绝!三星Galaxy Z Fold5最