7-Java中的12个原子操作

2019-03-21  本文已影响0人  加夕

JDK 1.5之前通常使用synchronized来解决变量原子更新,JDK 1.5开始提供了java.util.concurrent.atomic包,这个包中的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式。

因为变量的类型有多种,所以atomic包中提供了12个类,属于4中类型的原子更新方式。atomic包里的类基本都是使用Unsafe实现的包装类。

1.原子更新基本类型类

以上3个类提供的方法几乎一模一样,本文仅以AtomicInteger为例进行讲解。

常用方法:

代码示例:

    static AtomicInteger ai = new AtomicInteger(1);
    public static void main(String[] args) {
        System.out.println(ai.getAndIncrement());//1
        System.out.println(ai.get());//2
    }

2.原子更新数组

以AtomicIntegerArray为例,常用方法如下:

代码示例:

    static int[] value = new int[]{1, 2};
    static AtomicIntegerArray aia = new AtomicIntegerArray(value);
    public static void main(String[] args) {
        aia.getAndSet(0, 3);
        System.out.println(aia.get(0));//3
        System.out.println(value[0]);//1
    }

注意:数组value通过构造方法传递进去,然后AtomicIntegerArray会将当前数组复制一份,所以当AtomicIntegerArray对内部的数组元素进行修改时,不会影响传入的数组。

3.原子更新引用类型

如果要原子更新多个变量,就需要使用原子更新引用类型提供的类。

以AtomicReference为例,代码示例:

    static AtomicReference<User> ar = new AtomicReference<>();
    public static void main(String[] args) {
        User user = new User("Shinichi", 15);
        ar.set(user);
        User updateUser = new User("Shinichi", 17);
        ar.compareAndSet(user, updateUser);
        System.out.println(ar.get().getName());//Shinichi
        System.out.println(ar.get().getOld());//17
        System.out.println(user.getOld());//15
    }
    static class User {
        private String name;
        private int old;
        public User(String name, int old) {
            this.name = name;
            this.old = old;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getOld() {
            return old;
        }
        public void setOld(int old) {
            this.old = old;
        }
    }

4.原子更新属性(字段)类

如果需要原子地更新某个类里的某个字段时,就需要使用原子更新字段类。

要想原子地更新字段类需要两步。

以AtomicIntegerFieldUpdater为例,示例代码:

    //创建原子更新器,并设置需要更新的对象类和对象的属性
    static AtomicIntegerFieldUpdater<User> aifu = AtomicIntegerFieldUpdater.newUpdater(User.class, "old");
    public static void main(String[] args) {
        //设置柯南的年龄是10岁
        User conan = new User("conan", 10);
        //柯南张了一岁,但是仍然会输出旧的年龄
        System.out.println(aifu.getAndIncrement(conan));//10
        //输出柯南现在的年龄
        System.out.println(aifu.get(conan));//11

        System.out.println(conan.getOld());//11
    }
    static class User {
        private String name;
        volatile int old;//这里修饰符不是public(同包的话package-private也不抛异常)或者不带volatile都会抛异常
        public User(String name, int old) {
            this.name = name;
            this.old = old;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getOld() {
            return old;
        }
        public void setOld(int old) {
            this.old = old;
        }
    }
上一篇 下一篇

猜你喜欢

热点阅读