并发编程(八)Unsafe&Atomic

简介: 并发编程(八)Unsafe&Atomic

Unsafe

通过反射获取Unsafe

public class UnsafeInstance {
    public static Unsafe reflectGetUnsafe() {
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            return (Unsafe) field.get(null);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("反射获取Unsafe失败");
        }
    }
}

分配直接内存

Unsafe unsafe = UnsafeInstance.reflectGetUnsafe();
long oneHundred = Long.MAX_VALUE;
long size = 1;
/*
* 调用allocateMemory分配内存
*/
long memoryAddress = unsafe.allocateMemory(size);
/*
* 将1写入到内存中
*/
unsafe.putAddress(memoryAddress, oneHundred);
/*
* 内存中读取数据
*/
long readValue = unsafe.getAddress(memoryAddress);
System.out.println("value : " + readValue);

读写屏障

    UnsafeInstance.reflectGetUnsafe().loadFence();//读屏障
        UnsafeInstance.reflectGetUnsafe().storeFence();//写屏障
        UnsafeInstance.reflectGetUnsafe().fullFence();//读写屏障

        Unsafe unsafe = UnsafeInstance.reflectGetUnsafe();
        unsafe.monitorEnter(object);
        //业务逻辑写在此处之间
        unsafe.monitorExit(object);

Atomic

AtomicInteger

public class AtomicIntegerTest {
    public static AtomicInteger ATOMIC_INTEGER = new AtomicInteger(0);
    public static volatile int number = 0;
    public static void main(String[] args) throws InterruptedException {
        List<Thread> list1 = new ArrayList<>(10);
        List<Thread> list2 = new ArrayList<>(10);
        for (int i = 0; i < 10; i++) {
            Thread t =  new Thread(() -> {
                for (int j = 0; j < 10000; j++) {
                    ATOMIC_INTEGER.incrementAndGet();
                }
            }, "Thread-" + i);
            list1.add(t);
        }
        for (int i = 0; i < 10; i++) {
            Thread t = new Thread(() -> {
                for (int j = 0; j < 10000; j++) {
                    number++;
                }
            }, "Thread-" + i);
            list2.add(t);
        }
        list1.forEach(Thread::start);
        list2.forEach(Thread::start);
        TimeUnit.SECONDS.sleep(1);
        System.out.println(ATOMIC_INTEGER.get());
        System.out.println(number);
    }
}

AtomicIntegerArray

public class AtomicIntegerArrayTest {
    private static int[] ARR = {1,2};
    private static AtomicIntegerArray ATOMIC_ARRAY = new AtomicIntegerArray(ARR);
    public static void main(String[] args) {
        ATOMIC_ARRAY.set(0,3);
        System.out.println(ATOMIC_ARRAY.get(0));
        System.out.println(ARR[0]);
    }
}

AtomicReference

public class AtomicReferenceTest {
    private static AtomicReference<User> atomicReference = new AtomicReference<>(new User());
    private static AtomicInteger count = new AtomicInteger();
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 100; i++) {
            int finalI = i;
            new Thread(() -> {
                User user = atomicReference.get();
                wait(finalI*100000);//等待一会,模拟并发
                User user1 = new User();
                if (atomicReference.compareAndSet(user, user1)) {
                    count.incrementAndGet();
                }
            }).start();
        }
        TimeUnit.SECONDS.sleep(1);
        System.out.println("修改成功次数:" + count.get());
    }
    public static void wait(final int time) {
        for (int i = 0; i < time; i++) {
        }
    }
}

AtomicIntegerFieldUpdater

public class AtomicIntegerFieldUpdateTest {
    static AtomicIntegerFieldUpdater<User> atomicIntegerFieldUpdater = AtomicIntegerFieldUpdater.newUpdater(User.class, "age");
    static AtomicReferenceFieldUpdater<User, String> atomicReferenceFieldUpdater = AtomicReferenceFieldUpdater.newUpdater(User.class, String.class, "username");
    public static void main(String[] args) {
        User user = new User();
        atomicIntegerFieldUpdater.set(user,18);
        atomicReferenceFieldUpdater.set(user,"lzj");
        System.out.println(atomicIntegerFieldUpdater.get(user));
        System.out.println(atomicReferenceFieldUpdater.get(user));
    }
}

ABA问题

public class AtomicABAProblem {
    private static AtomicInteger atomicInteger = new AtomicInteger(10);
    public static void main(String[] args) {
        Thread owner = new Thread(() -> {
            int money = atomicInteger.get();
            System.out.println("第一次查看金库,金额:" + money);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("准备更新金库金额");
            if(atomicInteger.compareAndSet(money, 20))
                System.out.println("更新金库成功,金库剩余金额:"+atomicInteger.get());
            else
                System.err.println("更新失败,有人动了我的金库!");
        });
        Thread stealer = new Thread(() -> {
            int money = atomicInteger.addAndGet(-3);
            System.out.println("准备偷取金库,金库剩余金额" + money);
            //使用金额做点别的事,比如炒一波股
            money = atomicInteger.addAndGet(3);
            System.out.println("将金额还回金库,金库剩余金额" + money);
        });
        owner.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        stealer.start();
    }
}

ABA问题解决

public class SolveABAProblem {
    static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(10, 0);
    public static void main(String[] args) {
        Thread owner = new Thread(() -> {
            int money = atomicStampedReference.getReference();
            int stamp = atomicStampedReference.getStamp();
            System.out.println("第一次查看金库,金额:" + money + ",版本号:" + stamp);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("准备更新金库金额");
            if (atomicStampedReference.compareAndSet(money, 20, stamp, stamp + 1))
                System.out.println("更新金库成功,金库剩余金额:" + atomicStampedReference.getReference() + " 版本号:" + atomicStampedReference.getStamp());
            else
                System.err.println("更新失败,有人动了我的金库!");
        });
        Thread stealer = new Thread(() -> {
            int[] stamp = new int[1];
            int current = atomicStampedReference.get(stamp);
            int remain = 7;
            boolean success = atomicStampedReference.compareAndSet(current, remain, stamp[0], stamp[0] + 1);
            if(success){
                System.out.println("准备偷取金库,金库剩余金额" + remain);
                //使用金额做点别的事,比如炒一波股
                success =  atomicStampedReference.compareAndSet(remain, current, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
                if(success){
                    System.out.println("将金额还回金库,金库剩余金额" + atomicStampedReference.getReference());
                }else {
                    System.err.println("完了,还回失败了");
                }
            }else {
                System.err.println("偷取失败了");
            }
        });
        owner.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        stealer.start();
    }
}

自定义原子类

public class MyAtomicInteger {
    private static final Unsafe unsafe = UnsafeInstance.reflectGetUnsafe();
    private static final long valueOffset;
    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                    (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }
    private volatile int value;
    public MyAtomicInteger(int initialValue) {
        value = initialValue;
    }
    public int get() {
        return value;
    }
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
    public static void main(String[] args) {
        MyAtomicInteger myAtomicInteger = new MyAtomicInteger(10);
        int i = myAtomicInteger.get();
        int update = i + 1;
        boolean b = myAtomicInteger.compareAndSet(i, update);
        System.out.println(b);
        System.out.println(myAtomicInteger.get());
    }
}
目录
相关文章
|
存储 C++
两数相加(C++)
两数相加(C++)
108 0
|
存储 SQL 分布式计算
大数据-162 Apache Kylin 全量增量Cube的构建 Segment 超详细记录 多图
大数据-162 Apache Kylin 全量增量Cube的构建 Segment 超详细记录 多图
216 3
|
8月前
|
JavaScript Java 开发工具
深度解析:初学编程首句代码为 “Hello World” 的原因-优雅草卓伊凡
深度解析:初学编程首句代码为 “Hello World” 的原因-优雅草卓伊凡
119 0
深度解析:初学编程首句代码为 “Hello World” 的原因-优雅草卓伊凡
阿里云实名认证api接口怎么调用
当我们注册一个购物网站,或者下载某个游戏,很多地方都需要做实名认证。那么作为购物网站,或者游戏公司,怎么才能判断客户提供的身份证号码是否真实呢?游戏玩家越来越多,我们可能人工去审核这个人提供个的身份证号码是否属实,或者是否是真人。根据国家规定,我们很多游戏都要对未成年游戏时长进行控制,也就是通常大家所谓的游戏防沉迷系统。我们只要把那些进行实名认证玩家的年龄给摘出来以后,就可以判断其是否成年。
阿里云实名认证api接口怎么调用
关于处理电商系统订单状态的流转,分享下我的技术方案(附带源码)
关于处理电商系统订单状态的流转,分享下我的技术方案(附带源码)
687 0
satoken+webflux获取header以及body
satoken+webflux获取header以及body
320 0
|
存储 Shell Linux
【Shell 命令集合 系统设置 】Linux 管理系统服务 chkconfig命令 使用指南
【Shell 命令集合 系统设置 】Linux 管理系统服务 chkconfig命令 使用指南
241 0
|
NoSQL Java Apache
SpringBoot搭建基于Apache Shiro+Redis的分布式Session共享功能
我们在上一遍文档中已经完成了Shiro验证功能。(http://www.cnblogs.com/nbfujx/p/7773789.html),在此基础上我们将完成分布式Session共享功能。 Redis的使用 Maven Plugin添加Redis相关jar包 1 2 org.
5049 0