Concurrent programming in java-implement AtomicInteger class with Unsafe

Implement AtomicInteger class with Unsafe

Principle
AtomicInteger can achieve atomic updates under concurrent conditions, avoiding the use of synchronized, and the performance is very high.
Insert picture description here

The bottom layer of AtomicInteger is implemented with Unsafe. Here we hand-write an AtomicInteger class and test it.
Test example
Start 1000 threads, and each thread does -10 yuan operation. If the initial balance is 10000 then the correct result should be 0.
The following code passed the test in JDK1.8.

Account class

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

Account implementation class

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

DiyAtomicInteger class

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

}

test

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

Output

0 cost: 65 ms

Other-Unsafe tool class UnsafeAccessor

UnsafeThe construction method we know is private, and there is no getway to get the object, so we can only instantiate the Unsafeobject through reflection .

public final class Unsafe {
    
    
    private static final Unsafe theUnsafe;

    private Unsafe() {
    
    
    }
    ...
}

and so

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

Project code

Guess you like

Origin blog.csdn.net/e891377/article/details/109056446