Programación concurrente en la clase AtomicInteger de implementación java con Unsafe

Implementar la clase AtomicInteger con Unsafe

Principio
AtomicInteger puede lograr actualizaciones atómicas en condiciones concurrentes, evitando el uso de sincronizados, y el rendimiento es muy alto.
Inserte la descripción de la imagen aquí

Unsafe implementa la capa inferior de AtomicInteger. Aquí escribimos a mano una clase AtomicInteger y la probamos.
Ejemplo de prueba
Inicie 1000 subprocesos y cada subproceso realiza una operación de -10 yuanes. Si el saldo inicial es 10000, el resultado correcto debería ser 0.
El siguiente código pasó la prueba en JDK1.8.

Clase de cuenta

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");
    }
}

Clase de implementación de cuenta

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);
    }
}

Clase 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;
    }

}

prueba

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

Salida

0 cost: 65 ms

Otra clase de herramienta no segura UnsafeAccessor

UnsafeEl método de construcción que conocemos es privado y no hay getforma de obtener el objeto, por lo que solo podemos instanciar el Unsafeobjeto a través de la reflexión .

public final class Unsafe {
    
    
    private static final Unsafe theUnsafe;

    private Unsafe() {
    
    
    }
    ...
}

y entonces

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;
    }
}

Código de proyecto

Supongo que te gusta

Origin blog.csdn.net/e891377/article/details/109056446
Recomendado
Clasificación