java.util.concurrent源码阅读 03 AtomicXXXFieldUpdater

虽然volatile实现了多线程的可见性, 用于多线程对某个变量的修改, 比如bool值的变化, 别的线程立即看到, 可以退出循环之类的后续操作. 但是volatile不是线程安全的, 对其修饰的变量++, 加法减法等操作保证不了线程安全.
为了实现普通volatile变量的原子操作, java.util.concurrent包提供了AtomicXXXfieldupdater类.
以AtomicIntegerFieldUpdater为例, 实现普通volatile int变量的原子操作.

import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

class Container {
    public volatile int no;
}

class Task extends Thread {
    private AtomicIntegerFieldUpdater updater =
            AtomicIntegerFieldUpdater.newUpdater(Container.class, "no");
    private Container c;

    public Task(Container c) {
        this.c = c;
    }
    @Override
    public void run() {
        System.out.println(updater.getAndIncrement(c));
        System.out.println(updater.getAndIncrement(c));
    }
}

public class UpdaterUsage {
    public static void main (String [] args) {
        Container c = new Container();
        Task t1 = new Task(c);
        Task t2 = new Task(c);
        t1.start();
        t2.start();
    }
}

运行结果:

0
2
1
3

多运行几次,可以看到加法是原子操作的.
下面看AtomicIntegerFieldUpdater的源码.
1.首先是类声明:

public abstract class  AtomicIntegerFieldUpdater {
    ...
}

可以看到AtomicIntegerFieldUpdater是一个抽象类.
2.构建AtomicIntegerFieldUpdater实例.

@CallerSensitive
public static  AtomicIntegerFieldUpdater newUpdater(Class tclass, String fieldName) {
    return new AtomicIntegerFieldUpdaterImpl(tclass, fieldName, Reflection.getCallerClass());
}

3.其余一些抽象方法.

protected AtomicIntegerFieldUpdater() {
}
public abstract boolean compareAndSet(T obj, int expect, int update);
public abstract boolean weakCompareAndSet(T obj, int expect, int update);
public abstract void set(T obj, int newValue);
public abstract void lazySet(T obj, int newValue);
public abstract int get(T obj);
public int getAndSet(T obj, int newValue) {
    for (;;) {
        int current = get(obj);
        if (compareAndSet(obj, current, newValue))
            return current;
    }
}
public int getAndIncrement(T obj) {
    for (;;) {
        int current = get(obj);
        int next = current + 1;
        if (compareAndSet(obj, current, next))
            return current;
    }
}
public int getAndDecrement(T obj) {
    for (;;) {
        int current = get(obj);
        int next = current - 1;
        if (compareAndSet(obj, current, next))
            return current;
    }
}
public int getAndAdd(T obj, int delta) {
    for (;;) {
        int current = get(obj);
        int next = current + delta;
        if (compareAndSet(obj, current, next))
            return current;
    }
}

public int incrementAndGet(T obj) {
    for (;;) {
        int current = get(obj);
        int next = current + 1;
        if (compareAndSet(obj, current, next))
            return next;
    }
}
public int decrementAndGet(T obj) {
    for (;;) {
        int current = get(obj);
        int next = current - 1;
        if (compareAndSet(obj, current, next))
            return next;
    }
}
public int addAndGet(T obj, int delta) {
    for (;;) {
        int current = get(obj);
        int next = current + delta;
        if (compareAndSet(obj, current, next))
            return next;
    }
}

方法的功能与AtomicInteger类似, 区别在于AtomicIntegerFieldUpdater需要将操作的对象作为参数传入.
4.最后, 是AtomicIntegerFieldUpdater的内部类AtomicIntegerFieldUpdaterImpl, 它继承了AtomicIntegerFieldUpdater.

private static class AtomicIntegerFieldUpdaterImpl extends AtomicIntegerFieldUpdater {
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private final long offset;
    private final Class tclass;
    private final Class cclass;

    AtomicIntegerFieldUpdaterImpl(Class tclass, String fieldName, Class caller) {
        Field field = null;
        int modifiers = 0;
        try {
            field = tclass.getDeclaredField(fieldName);
            modifiers = field.getModifiers();
            sun.reflect.misc.ReflectUtil.ensureMemberAccess(
                caller, tclass, null, modifiers);
            sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }

        Class fieldt = field.getType();
        if (fieldt != int.class)
            throw new IllegalArgumentException("Must be integer type");

        if (!Modifier.isVolatile(modifiers))
            throw new IllegalArgumentException("Must be volatile type");

        this.cclass = (Modifier.isProtected(modifiers) &&
                       caller != tclass) ? caller : null;
        this.tclass = tclass;
        offset = unsafe.objectFieldOffset(field);
    }

    private void fullCheck(T obj) {
        if (!tclass.isInstance(obj))
            throw new ClassCastException();
        if (cclass != null)
            ensureProtectedAccess(obj);
    }

    public boolean compareAndSet(T obj, int expect, int update) {
        if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
        return unsafe.compareAndSwapInt(obj, offset, expect, update);
    }

    public boolean weakCompareAndSet(T obj, int expect, int update) {
        if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
        return unsafe.compareAndSwapInt(obj, offset, expect, update);
    }

    public void set(T obj, int newValue) {
        if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
        unsafe.putIntVolatile(obj, offset, newValue);
    }

    public void lazySet(T obj, int newValue) {
        if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
        unsafe.putOrderedInt(obj, offset, newValue);
    }

    public final int get(T obj) {
        if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
        return unsafe.getIntVolatile(obj, offset);
    }

    private void ensureProtectedAccess(T obj) {
        if (cclass.isInstance(obj)) {
            return;
        }
        throw new RuntimeException(
            new IllegalAccessException("Class " +
                cclass.getName() +
                " can not access a protected member of class " +
                tclass.getName() +
                " using an instance of " +
                obj.getClass().getName()
            )
        );
    }
}

总体原理与AtomicInteger相同, 只是多了一个类访问权限的判断.

你可能感兴趣的:(java.util.concurrent源码阅读 03 AtomicXXXFieldUpdater)