Java CAS操作與Unsafe類(lèi)詳解
一、復(fù)習(xí)
計(jì)算機(jī)內(nèi)存模型,synchronized和volatile關(guān)鍵字簡(jiǎn)介
二、兩者對(duì)比
sychronized和volatile都解決了內(nèi)存可見(jiàn)性問(wèn)題
不同點(diǎn):
(1)前者是獨(dú)占鎖,并且存在者上下文切換的開(kāi)銷(xiāo)以及線程重新調(diào)度的開(kāi)銷(xiāo);后者是非阻塞算法,不會(huì)造成上下文切換的開(kāi)銷(xiāo)。
(2)前者可以保證操作的原子性,但是后者不能保證操作的原子性。
三、在什么情況下才會(huì)使用volatile
- 寫(xiě)入變量是不依賴當(dāng)前值的,如果是依賴當(dāng)前值的話,由于獲取-計(jì)算-寫(xiě)入,三者不是原子性操作,而volatile是保證原子性操作的。
- 變量沒(méi)有加鎖的時(shí)候,如果變量加鎖了,是可以保證內(nèi)存的可見(jiàn)性的因此不需要再使用volatile
四、Java中的原子性操作
- 原子性操作通俗的來(lái)講就是一組操作,要么都執(zhí)行成功,要么都執(zhí)行失敗,不存在執(zhí)行部分成功的情況
- 使用synchronized關(guān)鍵字既可以保證操作的原子性又可以保證內(nèi)存的可見(jiàn)性,volatile只能保證內(nèi)存的可見(jiàn)性,但是不能保證操作的原子性;synchronized固然好,但在高并發(fā)的情況下,由于它是一種獨(dú)占鎖,因此會(huì)引起性能低下的問(wèn)題。
五、Java中的CAS操作
- 定義:CAS(compare and swap)比較并交換,這是JDK提供的一種非阻塞算法,它通過(guò)硬件保證了比較-更新的原子性問(wèn)題。JDK中的Unsafe類(lèi)提供了一系列的compareAndSwap*方法,下面以compareAndSwapLong為例進(jìn)行講解
- boolean compare(Object obj,long offset,long expect,long update)
- 先分別解釋一下各個(gè)參數(shù),obj是一個(gè)對(duì)象的引用(也就是對(duì)象存儲(chǔ)的地址),offset是相對(duì)于前面地址的偏移量,expect是一個(gè)預(yù)想的值,update代表如果和預(yù)想的值一樣,那么就是使用update這個(gè)值來(lái)代替,并且返回true,否則返回false
- 這是處理器提供的一種原子性指令
六、ABA問(wèn)題
- 描述:線程1獲取變量x的值為A,然后嘗試修改為B,但是此時(shí)如果有另一個(gè)線程修改了x的值為B,同時(shí)又修改成了A,那么線程2的這個(gè)A和線程1之前的A就不是同一個(gè)A了
- 產(chǎn)生原因:環(huán)形依賴,變量的值從A到B,然后又從B到A,這樣只能一個(gè)方向輪轉(zhuǎn),如果是從A到B,然后從B到C就不會(huì)出現(xiàn)這種情況。
- 解決方式:JDK中的AtomicStampedReferece給每個(gè)變量一個(gè)時(shí)間戳,從而避免了ABA問(wèn)題
七、Unsafe類(lèi)
在JDK中的rt.jar包中有許多方法都是native的,這是一種硬件級(jí)別的操作,使用JNI來(lái)調(diào)用C++底層函數(shù)來(lái)操作。
1.long objectFieldOffset(Field field)
釋義:獲取某個(gè)對(duì)象的中的某個(gè)域值所在對(duì)象的中的內(nèi)存偏移量
try{ long value = Unsafe.objectFieldOffset(AutomicLong.class.getDeclaredField("value")); }catch(Exception e){ e.printStackTrace(); }
2.int arrayBaseOffset(Class arrayClass)
釋義:獲取數(shù)組中的第一個(gè)元素地址
3.int arrayIndexOffset(Class arrayClass)
釋義:獲取數(shù)組中第一個(gè)元素的字節(jié)大小
4.boolean compareAndSwapLong(Object obj,long offset,long expect,long update)
可以見(jiàn)上文
八、源碼:
所在包:com.ruigege.OtherFoundationOfConcurrent2
https://github.com/ruigege66/ConcurrentJava
以上就是Java CAS操作與Unsafe類(lèi)詳解的詳細(xì)內(nèi)容,更多關(guān)于Java CAS操作與Unsafe類(lèi)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JAVA操作MongoDB數(shù)據(jù)庫(kù)實(shí)例教程
MongoDB是一個(gè)文檔型數(shù)據(jù)庫(kù),是NOSQL家族中最重要的成員之一,下面這篇文章主要給大家介紹了關(guān)于JAVA操作MongoDB數(shù)據(jù)庫(kù)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05Java案例使用集合方法實(shí)現(xiàn)統(tǒng)計(jì)任意字符串中字符出現(xiàn)的次數(shù)
這篇文章主要介紹了Java案例使用集合方法實(shí)現(xiàn)統(tǒng)計(jì)任意字符串中字符出現(xiàn)的次數(shù),下面我們將用兩種方法實(shí)現(xiàn),需要的小伙伴可以參考一下文章具體內(nèi)容2022-04-04java多線程Synchronized實(shí)現(xiàn)可見(jiàn)性原理解析
這篇文章主要介紹了java多線程Synchronized實(shí)現(xiàn)可見(jiàn)性原理,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12使用filter實(shí)現(xiàn)url級(jí)別內(nèi)存緩存示例
這篇文章主要介紹了使用filter實(shí)現(xiàn)url級(jí)別內(nèi)存緩存示例,只需要一個(gè)靜態(tài)類(lèi),在filter中調(diào)用,也可以全部寫(xiě)到filt里面。可以根據(jù)查詢參數(shù)分別緩存,需要的朋友可以參考下2014-03-03Java實(shí)現(xiàn)文件分片上傳接口的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用Java語(yǔ)言實(shí)現(xiàn)文件分片上傳的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2022-07-07SpringBoot配置Https入門(mén)實(shí)踐
本文主要介紹了SpringBoot配置Https入門(mén)實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-11-11