并发编程(八)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());

    }
}

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×