加入CODE CHINA

· 不限速    · 不限空间    · 不限人数    · 私仓免费

免费加入
    README.md

    用Unsafe实现AtomicInteger类

    原理 AtomicInteger可以在并发情况下达到原子化更新,避免使用了synchronized,而且性能非常高。 在这里插入图片描述

    AtomicInteger的底层是用Unsafe来实现的,这里我们手写一个AtomicInteger类,并且测试一下。 测试例子 启动 1000 个线程,每个线程做 -10 元 的操作,如果初始余额为 10000 那么正确的结果应当是 0。 以下代码在JDK1.8通过测试。

    账户Account 类

    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 实现类

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

    测试

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

    输出

    0 cost: 65 ms

    其它——Unsafe工具类UnsafeAccessor

    我们知道Unsafe 的构造方法是私有的,也没有get方法可以获取对象,所以我们只能通过反射的方式来实例化Unsafe 对象。

    public final class Unsafe {
        private static final Unsafe theUnsafe;
    
        private Unsafe() {
        }
        ...
    }

    所以

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

    项目简介

    手写AtomicInteger类

    发行版本

    当前项目没有发行版本

    贡献者 1

    Z zhouwangwang @zhouwangwang

    开发语言

    • Java 100.0 %