Programmation simultanée dans la classe AtomicInteger avec implémentation Java avec Unsafe

Implémenter la classe AtomicInteger avec Unsafe

Principe
AtomicInteger peut réaliser des mises à jour atomiques dans des conditions simultanées, évitant l'utilisation de synchronized, et les performances sont très élevées.
Insérez la description de l'image ici

La couche inférieure d'AtomicInteger est implémentée par Unsafe. Ici, nous écrivons manuellement une classe AtomicInteger et la testons.
Exemple de test
Démarrez 1000 threads et chaque thread effectue une opération de -10 yuans. Si le solde initial est de 10 000, le résultat correct doit être 0.
Le code suivant a réussi le test dans JDK1.8.

Classe de compte

interface Account {
    
    
    // 获取余额
    Integer getBalance();

    // 取款
    void withdraw(Integer amount);

    /**
     * 方法内会启动 1000 个线程,每个线程做 -10 元 的操作
     * 如果初始余额为 10000 那么正确的结果应当是 0
     */
    static void demo(Account account) {
    
    
        List<Thread> ts = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
    
    
            ts.add(new Thread(() -> {
    
    
                account.withdraw(10);
            }));
        }
        long start = System.nanoTime();
        ts.forEach(Thread::start);
        ts.forEach(t -> {
    
    
            try {
    
    
                t.join();
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        });
        long end = System.nanoTime();
        System.out.println(account.getBalance()
                + " cost: " + (end-start)/1000_000 + " ms");
    }
}

Classe d'implémentation de compte

class DiyAccount implements Account {
    
    

    private DiyAtomicInteger balance;

    public DiyAccount(int balance) {
    
    
        this.balance = new DiyAtomicInteger(balance);
    }

    @Override
    public Integer getBalance() {
    
    
        return balance.getValue();
    }

    @Override
    public void withdraw(Integer amount) {
    
    
        balance.decrement(amount);
    }
}

Classe DiyAtomicInteger

class DiyAtomicInteger {
    
    
    private volatile int value; //实例操作的变量
    private static final long valueOffset;//偏移量
    private static final Unsafe UNSAFE;// unsafe实例对象

    static {
    
    
        UNSAFE = UnsafeAccessor.getUnsafe();
        try {
    
    
            valueOffset = UNSAFE.objectFieldOffset(DiyAtomicInteger.class.getDeclaredField("value"));
        } catch (NoSuchFieldException e) {
    
    
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public int getValue() {
    
    
        return value;
    }

    public void decrement(int amount) {
    
    
        while (true) {
    
    
            int prev = this.value;
            int next = prev - amount;
            if (UNSAFE.compareAndSwapInt(this, valueOffset, prev, next)) {
    
    
                break;
            }
        }
    }

    public DiyAtomicInteger(int value) {
    
    
        this.value = value;
    }

}

tester

public class Test {
    
    
    public static void main(String[] args) {
    
    
        Account account = new DiyAccount(10000);
        Account.demo(account);
    }
}

Production

0 cost: 65 ms

Classe d'outils Other-Unsafe UnsafeAccessor

UnsafeLa méthode de construction que nous connaissons est privée et il n'y a aucun getmoyen d'obtenir l'objet, nous ne pouvons donc instancier l' Unsafeobjet que par réflexion .

public final class Unsafe {
    
    
    private static final Unsafe theUnsafe;

    private Unsafe() {
    
    
    }
    ...
}

et donc

import sun.misc.Unsafe;
import java.lang.reflect.Field;

public class UnsafeAccessor {
    
    
    private static final 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);
        }
    }

    public static Unsafe getUnsafe() {
    
    
        return unsafe;
    }
}

Code de projet

Je suppose que tu aimes

Origine blog.csdn.net/e891377/article/details/109056446
conseillé
Classement