亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中的Unsafe工具類使用詳解

 更新時(shí)間:2023年12月16日 09:30:31   作者:小晨想好好學(xué)習(xí)  
這篇文章主要介紹了Java中的Unsafe工具類使用詳解,Unsafe是jdk提供的一個(gè)直接訪問(wèn)操作系統(tǒng)資源的工具類(底層c++實(shí)現(xiàn)),它可以直接分配內(nèi)存,內(nèi)存復(fù)制,copy,提供cpu級(jí)別的CAS樂(lè)觀鎖等操作,需要的朋友可以參考下

一、Unsafe是什么?

Unsafe是jdk提供的一個(gè)直接訪問(wèn)操作系統(tǒng)資源的工具類(底層c++實(shí)現(xiàn)),它可以直接分配內(nèi)存,內(nèi)存復(fù)制,copy,提供cpu級(jí)別的CAS樂(lè)觀鎖等操作。

Unsafe位于sun.misc包下,jdk中的并發(fā)編程包juc(java.util.concurrent)基本全部靠Unsafe實(shí)現(xiàn),由此可見其重要性。

二、Unsafe對(duì)象的獲取

查看源碼:

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

結(jié)論:

  • Unsafe是餓漢式的單例模式
  • 只允許被引導(dǎo)類加載器(BootstrapClassLoader)加載的類使用,查看源碼可以看到在獲取unsafe對(duì)象時(shí)會(huì)判斷調(diào)用類是否是系統(tǒng)類加載器加載的,所以我們無(wú)法在自己的類中直接通過(guò)Unsafe.getUnsafe()獲取unsafe對(duì)象。所以只能通過(guò)反射直接new一個(gè)或者將其內(nèi)部靜態(tài)成員變量theUnsafe獲取出來(lái)
public static void main(String[] args) throws Exception{
    Class<Unsafe> unsafeClass = Unsafe.class;
    //方法一:通過(guò)反射構(gòu)造一個(gè)Unsafe對(duì)象
    Constructor<Unsafe> constructor = unsafeClass.getDeclaredConstructor();
    constructor.setAccessible(true);
    Unsafe unsafe1 = constructor.newInstance();
    System.out.println(unsafe1);
    //方法二:獲取內(nèi)部靜態(tài)成員變量
    Field theUnsafe = unsafeClass.getDeclaredField("theUnsafe");
    theUnsafe.setAccessible(true);
    Unsafe unsafe2 = (Unsafe) theUnsafe.get(null);
    System.out.println(unsafe2);
}

三、CAS

CAS譯為Compare And Swap,它是樂(lè)觀鎖的一種實(shí)現(xiàn)。假設(shè)主存值為pre,預(yù)期值為expect,想要更新成得值為update,當(dāng)且僅當(dāng)主存值pre等預(yù)期值expect時(shí),才將pre更新為update。

1、相關(guān)方法

在unsafe中,實(shí)現(xiàn)CAS算法通過(guò)cpu的原子指令cmpxchg實(shí)現(xiàn),它對(duì)應(yīng)的方法如下:

在這里插入圖片描述

簡(jiǎn)單介紹下它使用的參數(shù):

  • 第一個(gè)參數(shù) var1為內(nèi)存中要操作的對(duì)象
  • 第二個(gè)參數(shù) var2為要操作的值的內(nèi)存地址偏移量
  • 第三個(gè)參數(shù) var4為預(yù)期值
  • 第四個(gè)參數(shù) var5 為想要更新成的值

為了方便理解,舉個(gè)栗子。類User有一個(gè)成員變量name。我們new了一個(gè)對(duì)象User后,就知道了它(User對(duì)象)在內(nèi)存中的起始值,而員變量name在對(duì)象中的位置偏移是固定的。這樣通過(guò)這個(gè)起始值和這個(gè)偏移量就能夠定位到成員變量name在內(nèi)存中的具體位置。

如何得出name在對(duì)象User中的偏移量,Unsafe自然也提供了相應(yīng)的方法:

在這里插入圖片描述

2、demo

import sun.misc.Unsafe;
import java.lang.reflect.*;
public class UnsafeDemo {
    public static void main(String[] args) throws Exception {
        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafe.setAccessible(true);
        Unsafe unsafe = (Unsafe) theUnsafe.get(null);
        User user = new User("jsbintask");
        long nameOffset = unsafe.objectFieldOffset(User.class.getDeclaredField("name"));
        boolean res1 = unsafe.compareAndSwapObject(user, nameOffset, "jsbintask1", "jsbintask2");
        System.out.println(res1+", 第一次更新后的值:" + user.getName());
        boolean res2 = unsafe.compareAndSwapObject(user, nameOffset, "jsbintask", "jsbintask2");
        System.out.println(res2+", 第二次更新后的值:" + user.getName());
    }
    public static class User {
        private String name;
            public User(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }
    }  
}

在這里插入圖片描述

因?yàn)閮?nèi)存中name的值為"jsbintask",而第一次使用compareAndSwapObject方法預(yù)期值為"jsbintask1",這顯然是不相等的,所以第一次更新失敗,返回false。第二次我們傳入了正確的預(yù)期值,返回true,更新成功!

四、內(nèi)存分配

Unsafe還給我們提供了直接分配內(nèi)存,釋放內(nèi)存,拷貝內(nèi)存,內(nèi)存設(shè)置等方法,值得注意的是,這里的內(nèi)存指的是堆外內(nèi)存!它是不受jvm內(nèi)存模型掌控的,所以使用需要及其小心

在這里插入圖片描述

之后用到的時(shí)候再進(jìn)行補(bǔ)充

五、線程調(diào)度

通過(guò)Unsafe還可以直接將某個(gè)線程掛起,這和調(diào)用Object.wait()方法作用是一樣的,但是效率確更高!

在這里插入圖片描述

我們熟知的AQS(AbstractQueuedSynchronizer)內(nèi)部掛起線程使用了LockSupport,而LockSupport內(nèi)部依舊使用的是Unsafe:

到此這篇關(guān)于Java中的Unsafe工具類使用詳解的文章就介紹到這了,更多相關(guān)Unsafe工具類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java實(shí)現(xiàn)簡(jiǎn)單猜數(shù)字

    java實(shí)現(xiàn)簡(jiǎn)單猜數(shù)字

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單猜數(shù)字,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • SpringBoot2.3定制錯(cuò)誤頁(yè)面的方法示例

    SpringBoot2.3定制錯(cuò)誤頁(yè)面的方法示例

    這篇文章主要介紹了SpringBoot2.3定制錯(cuò)誤頁(yè)面的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • IDEA x64 exe文件打不開,bat能打開問(wèn)題

    IDEA x64 exe文件打不開,bat能打開問(wèn)題

    這篇文章主要介紹了IDEA x64 exe文件打不開,bat能打開問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • Intellij IDEA 2017.3使用Lombok及常用注解介紹

    Intellij IDEA 2017.3使用Lombok及常用注解介紹

    這篇文章主要介紹了Intellij IDEA 2017.3使用Lombok及常用注解介紹,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • springboot中手動(dòng)提交事務(wù)的實(shí)現(xiàn)方法

    springboot中手動(dòng)提交事務(wù)的實(shí)現(xiàn)方法

    手動(dòng)提交事務(wù)可以提供更靈活的控制,以便在分布式環(huán)境中處理事務(wù)的提交和回滾,本文就來(lái)介紹一下springboot中手動(dòng)提交事務(wù)的實(shí)現(xiàn)方法,感興趣的可以了解一下
    2024-01-01
  • Java中InputSteam怎么轉(zhuǎn)String

    Java中InputSteam怎么轉(zhuǎn)String

    面了一位實(shí)習(xí)生,叫他給我說(shuō)一下怎么把InputStream轉(zhuǎn)換為String,這種常規(guī)的操作,他竟然都沒(méi)有用過(guò)我準(zhǔn)備結(jié)合工作經(jīng)驗(yàn),整理匯集出了InputStream 到String 轉(zhuǎn)換的十八般武藝,助大家闖蕩 Java 江湖一臂之力,需要的朋友可以參考下
    2021-06-06
  • 淺談Java鎖的膨脹過(guò)程以及一致性哈希對(duì)鎖膨脹的影響

    淺談Java鎖的膨脹過(guò)程以及一致性哈希對(duì)鎖膨脹的影響

    本文主要介紹了Java鎖的膨脹過(guò)程以及一致性哈希對(duì)鎖膨脹的影響,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Java使用反射獲取list泛型過(guò)程淺析

    Java使用反射獲取list泛型過(guò)程淺析

    這篇文章主要介紹了Java使用反射獲取list泛型過(guò)程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2023-02-02
  • 關(guān)于java數(shù)組與字符串相互轉(zhuǎn)換的問(wèn)題

    關(guān)于java數(shù)組與字符串相互轉(zhuǎn)換的問(wèn)題

    這篇文章主要介紹了java數(shù)組與字符串相互轉(zhuǎn)換的問(wèn)題,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-10-10
  • Spring?Security安全框架之記住我功能

    Spring?Security安全框架之記住我功能

    這篇文章主要介紹了Spring?Security安全框架之記住我,本次就來(lái)探究如何實(shí)現(xiàn)這種自動(dòng)登錄、記住我的功能,通過(guò)實(shí)例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-02-02

最新評(píng)論