網(wǎng)站加載慢圖片做延時(shí)加載有用百度關(guān)鍵詞怎么設(shè)置
本文概要
AtomicIntegerFieldUpdater
類提供了一種高效、簡(jiǎn)潔的方式來(lái)原子性地更新對(duì)象的volatile字段,無(wú)需使用重量級(jí)的鎖機(jī)制,它通過(guò)基于反射的API實(shí)現(xiàn)了細(xì)粒度的并發(fā)控制,提升了多線程環(huán)境下的性能表現(xiàn)。
AtomicIntegerFieldUpdater核心概念
AtomicIntegerFieldUpdater
類是一個(gè)用于原子更新字段值的工具類,它特別適用于在并發(fā)環(huán)境中,當(dāng)多個(gè)線程需要訪問(wèn)和修改某個(gè)對(duì)象的某個(gè)volatile
整型字段時(shí),能夠保證該字段更新的原子性。
模擬一個(gè)業(yè)務(wù)場(chǎng)景,假設(shè)有一個(gè)在線書店,每個(gè)書籍都有一個(gè)庫(kù)存數(shù)量字段,表示為int stockCount
,當(dāng)多個(gè)用戶同時(shí)購(gòu)買同一本書時(shí),系統(tǒng)需要確保庫(kù)存數(shù)量的減少是線程安全的,即不會(huì)出現(xiàn)超賣的情況。
在傳統(tǒng)的同步方法中,可能會(huì)使用synchronized
關(guān)鍵字或ReentrantLock
來(lái)同步整個(gè)庫(kù)存減少的方法,但這樣做的話,每次只有一個(gè)線程能夠執(zhí)行減少庫(kù)存的操作,其他線程必須等待,這在高并發(fā)環(huán)境下可能會(huì)導(dǎo)致性能瓶頸。
在這個(gè)場(chǎng)景中使用AtomicIntegerFieldUpdater
類的decrementAndGet
方法,這個(gè)方法會(huì)以原子方式將庫(kù)存數(shù)量減1,并返回更新后的值,同時(shí)它是以原子地更新庫(kù)存數(shù)量字段,而不需要對(duì)整個(gè)方法進(jìn)行同步,多個(gè)線程可以同時(shí)嘗試減少庫(kù)存,但每次只有一個(gè)線程能夠成功更新庫(kù)存數(shù)量,其他線程會(huì)重新嘗試,直到成功為止。
注意:使用AtomicIntegerFieldUpdater
類時(shí),庫(kù)存數(shù)量字段必須是volatile
修飾的,這樣可以保證所有線程都能看到最新的值,同時(shí)由于AtomicIntegerFieldUpdater
類是基于反射實(shí)現(xiàn)的,因此,它只能更新公共字段或具有公共setter方法的字段。
AtomicIntegerFieldUpdater使用案例
下面是一個(gè)簡(jiǎn)單的Java代碼案例,演示了如何使用AtomicIntegerFieldUpdater
類,如下代碼:
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; public class AtomicIntegerFieldUpdaterExample { // 定義一個(gè)包含volatile字段的類 static class MyObject { volatile value = 0; // 這個(gè)字段將被原子更新 } // 創(chuàng)建一個(gè)AtomicIntegerFieldUpdater實(shí)例,用于更新MyObject的value字段 private static final AtomicIntegerFieldUpdater<MyObject> updater = AtomicIntegerFieldUpdater.newUpdater(MyObject.class, "value"); public static void main(String[] args) { // 創(chuàng)建一個(gè)MyObject實(shí)例 MyObject myObject = new MyObject(); // 輸出初始值 System.out.println("Initial value: " + myObject.value); // 使用AtomicIntegerFieldUpdater原子地增加value字段的值 updater.incrementAndGet(myObject); // 輸出更新后的值 System.out.println("Value after increment: " + myObject.value); // 使用AtomicIntegerFieldUpdater原子地將value字段的值設(shè)置為100 updater.set(myObject, 100); // 輸出再次更新后的值 System.out.println("Value after setting to 100: " + myObject.value); }
}
輸出將是:
Initial value: 0
Value after increment: 1
Value after setting to 100: 100
代碼解釋:
- 定義一個(gè)名為
MyObject
的靜態(tài)內(nèi)部類,該類有一個(gè)volatile
字段value
。 - 創(chuàng)建一個(gè)
AtomicIntegerFieldUpdater
類的實(shí)例updater
,該實(shí)例將用于原子地更新MyObject
類的value
字段。 - 在
main
方法中,創(chuàng)建了MyObject
的實(shí)例,并使用updater
原子地增加和設(shè)置value
字段的值。 - 使用
System.out.println
來(lái)輸出value
字段的初始值、增加后的值和設(shè)置為100后的值。
AtomicIntegerFieldUpdater核心API
AtomicIntegerFieldUpdater
類是Java的java.util.concurrent.atomic
包中的一個(gè)工具類,這個(gè)類的主要是用于原子地更新指定對(duì)象的指定volatile
字段,以下是該類中一些主要方法的含義:
newUpdater(Class<T> tclass, String fieldName)
:
這是一個(gè)靜態(tài)方法,用于創(chuàng)建一個(gè)新的AtomicIntegerFieldUpdater
,它能夠以原子方式更新給定類的指定名稱的volatile
字段,tclass
是字段所在類的Class
對(duì)象,fieldName
是要更新的字段的名稱。get(T obj)
:
這個(gè)方法獲取指定對(duì)象的volatile
字段的當(dāng)前值,obj
是包含要獲取字段的對(duì)象。set(T obj, int newValue)
:
這個(gè)方法以原子方式設(shè)置指定對(duì)象的volatile
字段的值為newValue
,obj
是包含要設(shè)置字段的對(duì)象,newValue
是要設(shè)置的新值。lazySet(T obj, int newValue)
:
這個(gè)方法最終將設(shè)置指定對(duì)象的volatile
字段的值為newValue
,但它允許之后的內(nèi)存操作重排序,也就是說(shuō)這個(gè)操作可能不是立即對(duì)其他線程可見的,它通常用于提高性能,但犧牲了一些一致性保證。getAndSet(T obj, int newValue)
:
這個(gè)方法以原子方式設(shè)置指定對(duì)象的volatile
字段的值為newValue
,并返回該字段的舊值,obj
是包含要設(shè)置字段的對(duì)象,newValue
是要設(shè)置的新值。getAndAdd(T obj, int delta)
:
這個(gè)方法以原子方式將給定值delta
添加到指定對(duì)象的volatile
字段的當(dāng)前值,并返回更新前的值,obj
是包含要添加字段的對(duì)象,delta
是要添加的值。incrementAndGet(T obj)
:
這個(gè)方法以原子方式將指定對(duì)象的volatile
字段的當(dāng)前值增加1,并返回更新后的值,obj
是包含要增加字段的對(duì)象。decrementAndGet(T obj)
:
這個(gè)方法以原子方式將指定對(duì)象的volatile
字段的當(dāng)前值減少1,并返回更新后的值,obj
是包含要減少字段的對(duì)象。addAndGet(T obj, int delta)
:
這個(gè)方法以原子方式將給定值delta
添加到指定對(duì)象的volatile
字段的當(dāng)前值,并返回更新后的值,obj
是包含要添加字段的對(duì)象,delta
是要添加的值。compareAndSet(T obj, int expect, int update)
:
這個(gè)方法以原子方式將指定對(duì)象的volatile
字段的值與expect
值進(jìn)行比較,如果當(dāng)前值等于expect
值,則使用update
值更新該字段,如果更新成功,則返回true
,否則返回false
,這個(gè)方法通常用于實(shí)現(xiàn)基于比較的同步機(jī)制,如自旋鎖。
使用AtomicIntegerFieldUpdater
時(shí),必須確保被更新的字段是volatile
修飾的,并且對(duì)于使用AtomicIntegerFieldUpdater
的類是可訪問(wèn)的(即字段是public
的,或者與AtomicIntegerFieldUpdater
在同一個(gè)包中且字段是包私有的,或者通過(guò)其他方式使字段可訪問(wèn)),此外,字段也不能是static
的。
AtomicIntegerFieldUpdater技術(shù)原理
AtomicIntegerFieldUpdater
類用于對(duì)對(duì)象的某個(gè)volatile
字段進(jìn)行原子性更新,該類的實(shí)現(xiàn)原理基于Java的內(nèi)存模型(JMM)和Unsafe類的底層操作。
實(shí)現(xiàn)原理
- Java內(nèi)存模型(JMM):使用Java內(nèi)存模型保證了多線程之間變量的可見性和原子性操作,使用
volatile
關(guān)鍵字確保了一個(gè)線程對(duì)變量的修改對(duì)其他線程是立即可見的,并且禁止了指令重排。 - Unsafe類:
AtomicIntegerFieldUpdater
的底層實(shí)現(xiàn)依賴于sun.misc.Unsafe
類,該類提供了低級(jí)別的、非安全的、操作系統(tǒng)級(jí)別的訪問(wèn)方法,它可以直接訪問(wèn)內(nèi)存、創(chuàng)建對(duì)象、數(shù)組等,而不受Java訪問(wèn)控制的限制。 - 反射:
AtomicIntegerFieldUpdater
使用反射來(lái)獲取要更新的字段的Field
對(duì)象,然后通過(guò)Unsafe
類直接操作這個(gè)字段的內(nèi)存地址。 - 原子操作:
Unsafe
類提供了一系列原子操作方法,如compareAndSwapInt
,這是一個(gè)基于硬件支持的原子比較并交換(CAS)操作,CAS操作包括三個(gè)參數(shù):一個(gè)內(nèi)存位置(V)、預(yù)期原值(A)和新值(B),如果內(nèi)存位置V的值與預(yù)期原值A(chǔ)相匹配,那么處理器會(huì)自動(dòng)將該位置的值更新為新值B,否則,處理器不做任何操作,無(wú)論哪種情況,它都會(huì)在CAS指令之前返回該位置的值,這一過(guò)程是原子的,也就是說(shuō)在執(zhí)行過(guò)程中不會(huì)被其他線程打斷。
底層算法
AtomicIntegerFieldUpdater
的底層算法主要基于CAS操作來(lái)實(shí)現(xiàn)原子性更新,以incrementAndGet
方法為例:
- 使用一個(gè)
do-while
循環(huán)來(lái)嘗試更新字段的值。 - 在循環(huán)體內(nèi),首先使用
Unsafe
類的getIntVolatile
方法獲取當(dāng)前字段的值。 - 計(jì)算新的值(當(dāng)前值 + 1)。
- 使用
Unsafe
類的compareAndSwapInt
方法嘗試將字段的值從當(dāng)前值更新為新值,如果成功,則退出循環(huán)并返回新值;如果失敗(說(shuō)明其他線程已經(jīng)修改了該字段的值),則繼續(xù)循環(huán)。
這種基于CAS的算法是一種無(wú)鎖算法,也稱為樂觀鎖算法,它不需要獲取和釋放鎖,而是通過(guò)不斷重試來(lái)確保更新的原子性,在高并發(fā)環(huán)境下,這種算法通常比傳統(tǒng)的基于鎖的算法具有更好的性能。
學(xué)習(xí)總結(jié)
AtomicIntegerFieldUpdater
類允許以原子方式更新對(duì)象的某個(gè)volatile
字段,而無(wú)需使用synchronized
關(guān)鍵字,這樣做的優(yōu)點(diǎn)在于減少了鎖的競(jìng)爭(zhēng),提升了多線程環(huán)境下的性能,并且使用簡(jiǎn)單,只需通過(guò)反射指定字段即可。
但是,由于使用了反射,所以字段必須是可訪問(wèn)的,這可能會(huì)破壞封裝性,并且,它只能更新volatile
類型的字段,對(duì)于其他類型的字段或者非volatile
字段則無(wú)能為力。
在使用AtomicIntegerFieldUpdater
時(shí),建議僅在確實(shí)需要原子性更新且性能是關(guān)鍵因素時(shí)使用,并且要要注意保持字段的可訪問(wèn)性,并確保字段是volatile
類型的。
END!
END!
END!
往期回顧
精品文章
Java并發(fā)基礎(chǔ):concurrent Flow API全面解析
Java并發(fā)基礎(chǔ):CopyOnWriteArraySet全面解析
Java并發(fā)基礎(chǔ):ConcurrentSkipListMap全面解析
Java并發(fā)基礎(chǔ):ConcurrentSkipListSet全面解析!
Java并發(fā)基礎(chǔ):SynchronousQueue全面解析!