Java concurrency之AtomicReference原子類_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
AtomicReference介紹和函數(shù)列表
AtomicReference是作用是對(duì)"對(duì)象"進(jìn)行原子操作。
AtomicReference函數(shù)列表
// 使用 null 初始值創(chuàng)建新的 AtomicReference。 AtomicReference() // 使用給定的初始值創(chuàng)建新的 AtomicReference。 AtomicReference(V initialValue) // 如果當(dāng)前值 == 預(yù)期值,則以原子方式將該值設(shè)置為給定的更新值。 boolean compareAndSet(V expect, V update) // 獲取當(dāng)前值。 V get() // 以原子方式設(shè)置為給定值,并返回舊值。 V getAndSet(V newValue) // 最終設(shè)置為給定值。 void lazySet(V newValue) // 設(shè)置為給定值。 void set(V newValue) // 返回當(dāng)前值的字符串表示形式。 String toString() // 如果當(dāng)前值 == 預(yù)期值,則以原子方式將該值設(shè)置為給定的更新值。 boolean weakCompareAndSet(V expect, V update)
AtomicReference源碼分析(基于JDK1.7.0_40)
在JDK1.7.0_40中AtomicReference.java的源碼如下:
public class AtomicReference<V> implements java.io.Serializable {
private static final long serialVersionUID = -1848883965231344442L;
// 獲取Unsafe對(duì)象,Unsafe的作用是提供CAS操作
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicReference.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
// volatile類型
private volatile V value;
public AtomicReference(V initialValue) {
value = initialValue;
}
public AtomicReference() {
}
public final V get() {
return value;
}
public final void set(V newValue) {
value = newValue;
}
public final void lazySet(V newValue) {
unsafe.putOrderedObject(this, valueOffset, newValue);
}
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
public final boolean weakCompareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
public final V getAndSet(V newValue) {
while (true) {
V x = get();
if (compareAndSet(x, newValue))
return x;
}
}
public String toString() {
return String.valueOf(get());
}
}
說明:
AtomicReference的源碼比較簡(jiǎn)單。它是通過"volatile"和"Unsafe提供的CAS函數(shù)實(shí)現(xiàn)"原子操作。
(01) value是volatile類型。這保證了:當(dāng)某線程修改value的值時(shí),其他線程看到的value值都是最新的value值,即修改之后的volatile的值。
(02) 通過CAS設(shè)置value。這保證了:當(dāng)某線程池通過CAS函數(shù)(如compareAndSet函數(shù))設(shè)置value時(shí),它的操作是原子的,即線程在操作value時(shí)不會(huì)被中斷。
AtomicReference示例
// AtomicReferenceTest.java的源碼
import java.util.concurrent.atomic.AtomicReference;
public class AtomicReferenceTest {
public static void main(String[] args){
// 創(chuàng)建兩個(gè)Person對(duì)象,它們的id分別是101和102。
Person p1 = new Person(101);
Person p2 = new Person(102);
// 新建AtomicReference對(duì)象,初始化它的值為p1對(duì)象
AtomicReference ar = new AtomicReference(p1);
// 通過CAS設(shè)置ar。如果ar的值為p1的話,則將其設(shè)置為p2。
ar.compareAndSet(p1, p2);
Person p3 = (Person)ar.get();
System.out.println("p3 is "+p3);
System.out.println("p3.equals(p1)="+p3.equals(p1));
}
}
class Person {
volatile long id;
public Person(long id) {
this.id = id;
}
public String toString() {
return "id:"+id;
}
}
運(yùn)行結(jié)果:
p3 is id:102 p3.equals(p1)=false
結(jié)果說明:
新建AtomicReference對(duì)象ar時(shí),將它初始化為p1。
緊接著,通過CAS函數(shù)對(duì)它進(jìn)行設(shè)置。如果ar的值為p1的話,則將其設(shè)置為p2。
最后,獲取ar對(duì)應(yīng)的對(duì)象,并打印結(jié)果。p3.equals(p1)的結(jié)果為false,這是因?yàn)镻erson并沒有覆蓋equals()方法,而是采用繼承自O(shè)bject.java的equals()方法;而Object.java中的equals()實(shí)際上是調(diào)用"=="去比較兩個(gè)對(duì)象,即比較兩個(gè)對(duì)象的地址是否相等。
相關(guān)文章
Spring Boot中數(shù)據(jù)庫(kù)操作Druid和HikariDataSource的詳細(xì)過程
這篇文章主要介紹了Spring Boot中數(shù)據(jù)庫(kù)操作Druid和HikariDataSource的詳細(xì)過程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06
Java實(shí)現(xiàn)評(píng)論回復(fù)功能的完整步驟
這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)評(píng)論回復(fù)功能的完整步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
mybatis-plus的自動(dòng)填充時(shí)間的問題(添加到數(shù)據(jù)庫(kù)的時(shí)間比當(dāng)前時(shí)間多4個(gè)小時(shí))
這篇文章主要介紹了mybatis-plus的自動(dòng)填充時(shí)間的問題(添加到數(shù)據(jù)庫(kù)的時(shí)間比當(dāng)前時(shí)間多4個(gè)小時(shí)),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09
Java Vector和ArrayList的異同分析及實(shí)例講解
在本篇文章里小編給大家整理的是一篇關(guān)于Java Vector和ArrayList的異同分析及實(shí)例講解內(nèi)容,有興趣的朋友們可以學(xué)習(xí)參考下。2021-01-01
MybatisPlus lambdaQueryWrapper中常用方法的使用
本文主要介紹了MybatisPlus lambdaQueryWrapper中常用方法的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
KafkaListener注解的實(shí)現(xiàn)機(jī)制源碼解析
這篇文章主要為大家介紹了KafkaListener注解的實(shí)現(xiàn)機(jī)制源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10

