java 如何知道对象是否被修改过_Java 并发编程:AQS 的原子性如何保证
當(dāng)我們研究AQS框架時(shí)(對(duì)于AQS不太熟知可以先閱讀《什么是JDK內(nèi)置并發(fā)框架AQS》,會(huì)發(fā)現(xiàn)AbstractQueuedSynchronizer這個(gè)類很多地方都使用了CAS操作。在并發(fā)實(shí)現(xiàn)中CAS操作必須具備原子性,而且是硬件級(jí)別的原子性。我們知道Java被隔離在硬件之上,硬件級(jí)別的操作明顯力不從心。這時(shí)為了能夠執(zhí)行操作系統(tǒng)層面的操作,就必須要通過用C++編寫的native本地方法來擴(kuò)展實(shí)現(xiàn)。一般可以通過JNI方式實(shí)現(xiàn)Java代碼調(diào)用C++代碼
Unsafe調(diào)用
JDK提供了一個(gè)類來滿足CAS的硬件級(jí)別原子性要求,即sun.misc.Unsafe類,從名字上大概知道它用于執(zhí)行低級(jí)別、不安全的操作,AQS就是使用此類來完成硬件級(jí)別的原子操作。也就是說通過該類就能實(shí)現(xiàn)對(duì)處理器的原子操作,Unsafe通過JNI調(diào)用本地C++代碼,C++代碼調(diào)用了硬件指令集,這些硬件指令集都屬于CPU。
Unsafe的魔法
Unsafe是一個(gè)很強(qiáng)大的類,它可以分配內(nèi)存、釋放內(nèi)存、可以定位對(duì)象某字段的位置、可以修改對(duì)象的字段值、可以使線程掛起、使線程恢復(fù)、可進(jìn)行硬件級(jí)別原子的CAS操作等等。
Unsafe的用途
一般情況下,我們都沒有特殊的需求去使用它。而且它的使用必須限定在受信任代碼,這些代碼一般由JVM指定。例如直接Unsafe unsafe = Unsafe.getUnsafe();獲取一個(gè)Unsafe實(shí)例是不會(huì)成功的,因?yàn)檫@個(gè)類的安全性很重要,設(shè)計(jì)者對(duì)其進(jìn)行了安全檢查。如下代碼所示,它會(huì)檢測(cè)調(diào)用它的類是否由啟動(dòng)類加載器Bootstrap ClassLoader(它的類加載器為null)加載,由此來保證此類只能由JVM指定的類使用。
Unsafe實(shí)現(xiàn)CAS
因?yàn)榇嬖诎踩詥栴},所以如果我們要用Unsafe類則需要另辟蹊徑。可行的方法就是通過反射來繞過上述的安全檢查,我們可以通過以下的getUnsafeInstance方法來獲取Unsafe實(shí)例。這段代碼演示了如何獲取Java對(duì)象的相對(duì)地址偏移量以及使用Unsafe來完成CAS操作,最終輸出的是flag字段的內(nèi)存偏移量及CAS操作后的值。最終的輸出為“unsafeTest對(duì)象的flag字段的地址偏移量為:12”和“CAS操作后的flag值為:101”。另外如果使用開發(fā)工具如Eclipse,可能會(huì)編譯通不過,只要把編譯錯(cuò)誤提示關(guān)掉即可。
總結(jié)
這里主要講解了Unsafe類如何讓Java層能實(shí)現(xiàn)硬件級(jí)別的原子操作,同時(shí)也了解了Unsafe類擁有很多法魔技能。通常我們使用Java時(shí)不需要在內(nèi)存中處理Java對(duì)象及內(nèi)存地址位置,但有的時(shí)候我們被迫必須要操作Java對(duì)象相關(guān)的地址,于是我們只能使用Unsafe類。使用該類則意味著破壞了Java平臺(tái)隔離的效果了,我們都知道一旦用了本地方法則可能會(huì)引來跨平臺(tái)問題。
Java 并發(fā)編程
- Java并發(fā)編程:AQS的原子性如何保證
- Java并發(fā)編程:如何防止在線程阻塞與喚醒時(shí)死鎖
- Java并發(fā)編程:多線程如何實(shí)現(xiàn)阻塞與喚醒
- Java并發(fā)編程:任務(wù)執(zhí)行器Executor接口
- Java并發(fā)編程:并發(fā)中死鎖的形成條件及處理
- Java并發(fā)編程:Java 序列化的工作機(jī)制
- Java并發(fā)編程:進(jìn)程、線程、并行與并發(fā)
總結(jié)
以上是生活随笔為你收集整理的java 如何知道对象是否被修改过_Java 并发编程:AQS 的原子性如何保证的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux如何修改主机名
- 下一篇: java 多线程同步问题_Java多线程