中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java如何使用Unsafe類

發布時間:2021-09-26 10:00:03 來源:億速云 閱讀:171 作者:小新 欄目:開發技術

這篇文章將為大家詳細講解有關Java如何使用Unsafe類,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

Unsafe 對象提供了非常底層的,操作內存、線程的方法,相當于開了后門。

在atomic類中CAS實現、LockSupport中park unpark的底層都調用了UnSafe中的方法。

UnSafe并不是說線程不安全,而是說操作內存有可能會造成不安全問題。

當然對于開發人員來說

Unsafe 對象不能直接調用,只能通過反射獲得

Java如何使用Unsafe類

通過反射獲得Unsafe對象

package com.dongguo.unsafe;

import sun.misc.Unsafe;

import java.lang.reflect.Field;

/**
 * @author Dongguo
 * @date 2021/9/12 0012-21:32
 * @description:
 */
public class UnsafeAccessor {
    static Unsafe unsafe;
    static {
        try {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            unsafe = (Unsafe) theUnsafe.get(null);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new Error(e);
        }
    }
    static Unsafe getUnsafe() {
        return unsafe;
    }

    public static void main(String[] args) {
        Unsafe unsafe = getUnsafe();
        System.out.println(unsafe);
    }
}

運行結果

sun.misc.Unsafe@7ea987ac

使用Unsafe實現 CAS 操作

package com.dongguo.unsafe;

import lombok.Data;
import sun.misc.Unsafe;

import java.lang.reflect.Field;

/**
 * @author Dongguo
 * @date 2021/9/12 0012-21:32
 * @description:
 */
public class UnsafeAccessor {
    static Unsafe unsafe;
    static {
        try {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            unsafe = (Unsafe) theUnsafe.get(null);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new Error(e);
        }
    }
    static Unsafe getUnsafe() {
        return unsafe;
    }

    public static void main(String[] args) throws NoSuchFieldException {
        Unsafe unsafe = getUnsafe();
        System.out.println(unsafe);

        Field id = Student.class.getDeclaredField("id");
        Field name = Student.class.getDeclaredField("name");
        // 獲得成員變量的偏移量
        long idOffset = unsafe.objectFieldOffset(id);
        long nameOffset = unsafe.objectFieldOffset(name);
        Student student = new Student();
        // 使用 cas 方法替換成員變量的值
        unsafe.compareAndSwapInt(student, idOffset, 0, 20); // 返回 true   0為舊值 20為新值
        unsafe.compareAndSwapObject(student, nameOffset, null, "張三"); // 返回 true 舊值為null,新值為張三
        System.out.println(student);
    }
}
@Data
class Student {
    volatile int id;
    volatile String name;
}

運行結果

sun.misc.Unsafe@7ea987ac
Student(id=20, name=張三)

直接使用Unsafe類實現之前AtomicIntegerFieldUpdater中線程安全的原子整數 BankAccount

在atomic中使用AtomicIntegerFieldUpdater實現money線程安全的原子整數

package com.dongguo.unsafe;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

/**
 * @author Dongguo
 * @date 2021/9/7 0007-14:41
 * 以一種線程安全的方式操作非線程安全對象的某些字段。
 * 需求:
 * 1000個人同時向一個賬號轉賬一元錢,那么累計應該增加1000元,
 * 除了synchronized和CAS,還可以使用AtomicIntegerFieldUpdater來實現。
 */
class BankAccount {
    private String bankName = "ACBC";
    public volatile int money = 0;
    AtomicIntegerFieldUpdater<BankAccount> fieldUpdater = AtomicIntegerFieldUpdater.newUpdater(BankAccount.class, "money");

    public void transferMoney(BankAccount bankAccount) {
        fieldUpdater.incrementAndGet(bankAccount);
    }
}

public class AtomicIntegerFieldUpdaterDemo {
    public static void main(String[] args) {
        BankAccount bankAccount = new BankAccount();

        for (int i = 1; i <= 1000; i++) {
            new Thread(() -> {
                bankAccount.transferMoney(bankAccount);
            }, String.valueOf(i)).start();
        }
        //暫停毫秒
        try {
            TimeUnit.MILLISECONDS.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(bankAccount.money);
    }

}

改為使用UnSafe實現money線程安全的原子整數

package com.dongguo.unsafe;

import sun.misc.Unsafe;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

/**
 * @author Dongguo
 * @date 2021/9/7 0007-14:41
 */
class BankAccount {
    private String bankName = "ACBC";
    public volatile int money;
    static final Unsafe unsafe;
    static final long DATA_OFFSET;

    static {
        unsafe = UnsafeAccessor.getUnsafe();
        try {
            // money 屬性在 BankAccount 對象中的偏移量,用于 Unsafe 直接訪問該屬性
            DATA_OFFSET = unsafe.objectFieldOffset(BankAccount.class.getDeclaredField("money"));
        } catch (NoSuchFieldException e) {
            throw new Error(e);
        }
    }

    public BankAccount(int money) {
        this.money = money;
    }

    public void transferMoney(int amount) {
        int oldValue;
        while (true) {
            // 獲取共享變量舊值,可以在這一行加入斷點,修改 data 調試來加深理解
            oldValue = money;
            // cas 嘗試修改 data 為 舊值 + amount,如果期間舊值被別的線程改了,返回 false
            if (unsafe.compareAndSwapInt(this, DATA_OFFSET, oldValue, oldValue + amount)) {
                return;
            }
        }
    }
}
public class AtomicIntegerFieldUpdaterDemo {
    public static void main(String[] args) {
        BankAccount bankAccount = new BankAccount(0);

        for (int i = 1; i <= 1000; i++) {
            new Thread(() -> {
                bankAccount.transferMoney(1);
            }, String.valueOf(i)).start();
        }
        //暫停毫秒
        try {
            TimeUnit.MILLISECONDS.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(bankAccount.money);
    }
}
運行結果
1000
/暫停毫秒
        try {
            TimeUnit.MILLISECONDS.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(bankAccount.money);
    }
}

運行結果

1000

關于“Java如何使用Unsafe類”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

菏泽市| 历史| 嘉荫县| 合作市| 辽中县| 南漳县| 遵义县| 庆安县| 穆棱市| 永丰县| 漠河县| 武城县| 遵义县| 筠连县| 古交市| 龙里县| 凤翔县| 原阳县| 广安市| 五原县| 阳江市| 大理市| 淄博市| 栾城县| 德保县| 潜江市| 甘洛县| 巧家县| 习水县| 大冶市| 阿城市| 兖州市| 松滋市| 康乐县| 墨脱县| 遵义县| 靖州| 登封市| 定州市| 淄博市| 包头市|