Java 并发程序员基础知识

【Java 并发笔记】13 种原子操作类相关整理

2019-01-15  本文已影响5人  58bc06151329

文前说明

作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。

本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。

1. 简介

synchronized(this){
    num++;
 }

2. 原子更新

2.1 原子更新基本类型

类名 说明
AtomicBoolean 原子更新布尔类型。
AtomicInteger 原子更新整型。
AtomicLong 原子更新长整型。
部分方法 说明
int addAndGet(int delta) 以原子方式将输入的数值与实例中的值想加,并返回结果。
boolean compareAndSet(int expect, int update) 若输入的数值等于预期值,则以原子方式将该值设置为输入的值。
int getAndIncrement() 以原子方式将当前值加1,返回的是自增前的值。
void lazySet(int newValue) 最终会设置成 new Value,使用 lazySet 设置后,可能会导致其他线程在之后的一小段时间内还是可以读到旧的值。
int getAndSet(int newValue) 以原子方式设置为 newValue 的值,并返回旧值。

addAndGet 方法

public final int addAndGet(int delta) {
       return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
}
public final int getAndSetInt(Object o, long offset, int newValue) {
        int v;
        do {
            v = getIntVolatile(o, offset);
        } while (!compareAndSwapInt(o, offset, v, newValue));
        return v;
}

compareAndSet 方法

public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

getAndIncrement 方法

public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
}

lazySet 方法

public final void lazySet(int newValue) {
        unsafe.putOrderedInt(this, valueOffset, newValue);
}

getAndSet 方法

public final int getAndSet(int newValue) {
        return unsafe.getAndSetInt(this, valueOffset, newValue);
}

原子更新基础类型示例

public class Test {
    private static AtomicInteger atomicInteger = new AtomicInteger(0);

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                public void run() {
                    System.out.println(atomicInteger.getAndIncrement());
                }
            }).start();
        }
        System.out.println(atomicInteger.get());
    }
}


/**
--- print ---
0
1
2
3
4
**/

2.2 原子更新数组

类名 说明
AtomicIntegerArray 原子更新整型数组里的元素。
AtomicLongArray 原子更新长整型数组里的元素。
AtomicReferenceArray 原子更新引用类型数组的元素。
AtomicBooleanArray 原子更新布尔类型数组的元素。
部分方法 说明
int addAndGet(int i, int delta) 以原子方式将输入值与数组中索引 i 的元素相加。
boolean compareAndSet(int i, int expect, int update) 若当前值等于预期值,则以原子方式将数组位置 i 的元素设置成 update 值。
get(int i) 获取索引为 i 的元素值。

addAndGet 方法

public final int addAndGet(int i, int delta) {
        return getAndAdd(i, delta) + delta;
}
public final int getAndAdd(int i, int delta) {
        return unsafe.getAndAddInt(array, checkedByteOffset(i), delta);
}

compareAndSet 方法

public final boolean compareAndSet(int i, int expect, int update) {
        return compareAndSetRaw(checkedByteOffset(i), expect, update);
}
private boolean compareAndSetRaw(long offset, int expect, int update) {
        return unsafe.compareAndSwapInt(array, offset, expect, update);
}

get 方法

public final int get(int i) {
        return getRaw(checkedByteOffset(i));
}

private int getRaw(long offset) {
        return unsafe.getIntVolatile(array, offset);
}

原子更新数组示例

public AtomicIntegerArray(int[] array) {
        // Visibility guaranteed by final field guarantees
        this.array = array.clone();
}
public class Test {

    static int[] value = new int[] { 1, 2 };
    static AtomicIntegerArray ai = new AtomicIntegerArray(value);

    public static void main(String[] args) {
        System.out.println(ai.get(0));
        ai.getAndSet(0, 3);
        System.out.println(ai.get(0));
        System.out.println(value[0]);
    }
}

/**
--- print ---
1
3
1
**/

2.3 原子更新引用

类名 说明
AtomicReference 原子更新引用类型。
AtomicReferenceFieldUpdater 原子更新引用类型里的字段。
AtomicMarkableReference 原子更新带有标记位的引用类型,构造方法是AtomicMarkableReference(V initialRef,boolean initialMark)

原子更新引用示例

public class Test {

    static class User {
        private String name = "";
        private int id;

        public User(String name, int id) {
            this.name = name;
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }
    }

    public static AtomicReference<User> ar = new AtomicReference<User>();

    public static void main(String[] args) {
        User user = new User("aa", 11);
        ar.set(user);
        User newUser = new User("bb", 22);
        ar.compareAndSet(user, newUser);
        System.out.println(ar.get().getName());
        System.out.println(ar.get().getId());
    }
}

/**
--- print ---
bb
22
**/

2.4 原子更新属性(字段)

类名 说明
AtomicIntegerFieldUpdater 原子更新整型的字段的更新器。
AtomicLongFieldUpdater 原子更新长整型字段的更新器。
AtomicStampedReference 原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于原子的更新数据和数据的版本号,可以解决使用 CAS 进行原子更新时可能出现的 ABA 问题

原子更新属性(字段)示例

public class Test {

    static class User {
        volatile String name = "";
        private int id;

        public User(String name, int id) {
            this.name = name;
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }
    }

    public static AtomicReferenceFieldUpdater updater =
            AtomicReferenceFieldUpdater.newUpdater(User.class, String.class, "name");

    public static void main(String[] args) {
        User user = new User("aa", 22);
        updater.compareAndSet(user, user.getName(), "bb");
        System.out.println(updater.get(user));
    }
}

/**
--- print ---
bb
**/
上一篇下一篇

猜你喜欢

热点阅读