JUC知识点框架

JUC(java.util.concurrent)

  • atomic

    • AtomicBoolean
    • AtomicInteger
    • AtomicLong
    • AtomicReference
    • LongAdder
  • locks

    • AQS(AbstractQueuedSynchronizer)
    • ReentrantLock
    • Condition
    • LockSupport
    • ReentrantReadWriteLock
    • StampedLock
  • AQS典型应用

    • ReentrantLock
    • CountDownLatch
    • Semaphore
    • CyclicBarrier
  • 容器

    • ConcurrentHashMap
    • CopyOnWriteArrayList
    • BlockingQueue(LinkedBlockingQueue,DelayQueue)
    • BlockingDeque(LinkedBlockingDeque)
  • 线程池

    • Executors
  • 其他

    • CompletableFuture
    • ForkJoinPool
    • FutureTask Callable

Unsafe类--JUC的CAS操作都是基于该类,下面是列举一些int类型的操作

public final class Unsafe {
    private static final Unsafe theUnsafe;
    //单例模式,禁止创建对象 
	private Unsafe() {
    }
	@CallerSensitive
    public static Unsafe getUnsafe() {
        Class var0 = Reflection.getCallerClass();
        if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
            throw new SecurityException("Unsafe");
        } else {
            return theUnsafe;
        }
    }
    /**
    *  一次CAS操作,将对象var1的属性(属性地址偏移量var2)由原值var4替换成期望值var5,
    *  替换成功则返回true,否则返回false
    *  
    *  Object var1 对象
    *  long var2 对象中属性的偏移量
    *  int var4 属性的原值
    *  int var5 属性期望值
    */
	public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
    /**
    *  while循环CAS操作,将对象var1的属性(属性地址偏移量var2)由替换成期望值var4,并返回原值var5
    *  
    *  Object var1 对象
    *  long var2 属性地址偏移量
    *  int var4 期望值
    *  return int var5 原值
    */
	public final int getAndSetInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var4));

        return var5;
    }
    /**
    *  while循环CAS操作,将对象var1的属性(属性地址偏移量var2)增加var4,并返回增加前的原值var5
    *  
    *  Object var1 对象
    *  long var2 对象中属性的偏移量
    *  int var4 属性的原值
    *  return int var5 属性期望值
    */
    public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

        return var5;
    }
    略....
}

AtomicInteger--支持int类型CAS操作(AtomicBoolean、AtomicLong与其雷同)

public class AtomicInteger extends Number implements java.io.Serializable {

    private static final long serialVersionUID = 6214790243416807050L;
    //unsafe 
    private static final Unsafe unsafe = Unsafe.getUnsafe();
	//属性地址偏移量
    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 AtomicInteger(int initialValue) {
        value = initialValue;
    }

    public AtomicInteger() {
    }


    public final int get() {
        return value;
    }

    public final void set(int newValue) {
        value = newValue;
    }
      /**
       * Atomically sets the value to the given updated value
       * if the current value {@code ==} the expected value.
       *
       * @param expect the expected value
       * @param update the new value
       * @return {@code true} if successful. False return indicates that
       * the actual value was not equal to the expected value.
       */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
	/**
     * Atomically sets to the given value and returns the old value.
     *  while循环CAS直至成功,并返回原值
     * @param newValue the new value
     * @return the previous value
     */
    public final int getAndSet(int newValue) {
        //见unsafe类 
        return unsafe.getAndSetInt(this, valueOffset, newValue);
    }
    /**
     * Atomically increments by one the current value.
     *
     * @return the previous value
     */
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }
    /**
     * Atomically adds the given value to the current value.
     * while循环CAS直至成功 返回原值
     * @param delta the value to add
     * @return the previous value
     */
    public final int getAndAdd(int delta) {
        //见unsafe类 
        return unsafe.getAndAddInt(this, valueOffset, delta);
    }
	    /**
     * Atomically adds the given value to the current value.
     *  while循环CAS直至成功 返回add结果值
     * @param delta the value to add
     * @return the updated value
     */
    public final int addAndGet(int delta) {
        //见unsafe类 while循环CAS直至成功
        return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
    }

}

LongAdder--与AtomicLong功能相同,但是实现不同,高并发场景下性能更佳

AtomicLong高并发场景下,一次只有一个线程成功,其他线程都失败,而LongAdder针对此场景做了优化。LongAdder继承了Striped64,Striped64里面有base 和cells数组两个属性,这两个属性之和为LongAdder保存的数值。没有线程竞争时add等操作直接修改base;多线程竞争时,线程根据自己的hash & (size -1)[size为cells数组的长度]来确定下标,并CAS方式修改cells对应下标的值,sum操作可以获取真实数值--将base 和cells累加。

abstract class Striped64 extends Number {
      /** Number of CPUS, to place bound on table size */
    static final int NCPU = Runtime.getRuntime().availableProcessors();

    /**
     * Table of cells. When non-null, size is a power of 2.
     */
    transient volatile Cell[] cells;

    /**
     * Base value, used mainly when there is no contention, but also as
     * a fallback during table initialization races. Updated via CAS.
     */
    transient volatile long base;

    /**
     * Spinlock (locked via CAS) used when resizing and/or creating Cells.
     */
    transient volatile int cellsBusy;
    略...
}

LongAdder

public class LongAdder extends Striped64 implements Serializable {

    public LongAdder() {
    }

    /**
     * Adds the given value.
     *
     * @param x the value to add
     */
    public void add(long x) {
        Cell[] as; long b, v; int m; Cell a;
        if ((as = cells) != null || !casBase(b = base, b + x)) {
            boolean uncontended = true;
            if (as == null || (m = as.length - 1) < 0 ||
                (a = as[getProbe() & m]) == null ||
                !(uncontended = a.cas(v = a.value, v + x)))
                longAccumulate(x, null, uncontended);
        }
    }

    /**
     * Equivalent to {@code add(1)}.
     */
    public void increment() {
        add(1L);
    }

    /**
     * Equivalent to {@code add(-1)}.
     */
    public void decrement() {
        add(-1L);
    }

    /**
     * Returns the current sum.  The returned value is <em>NOT</em> an
     * atomic snapshot; invocation in the absence of concurrent
     * updates returns an accurate result, but concurrent updates that
     * occur while the sum is being calculated might not be
     * incorporated.
     *
     * @return the sum
     */
    public long sum() {
        Cell[] as = cells; Cell a;
        long sum = base;
        if (as != null) {
            for (int i = 0; i < as.length; ++i) {
                if ((a = as[i]) != null)
                    sum += a.value;
            }
        }
        return sum;
    }

    /**
     * Resets variables maintaining the sum to zero.  This method may
     * be a useful alternative to creating a new adder, but is only
     * effective if there are no concurrent updates.  Because this
     * method is intrinsically racy, it should only be used when it is
     * known that no threads are concurrently updating.
     */
    public void reset() {
        Cell[] as = cells; Cell a;
        base = 0L;
        if (as != null) {
            for (int i = 0; i < as.length; ++i) {
                if ((a = as[i]) != null)
                    a.value = 0L;
            }
        }
    }

    /**
     * Equivalent in effect to {@link #sum} followed by {@link
     * #reset}. This method may apply for example during quiescent
     * points between multithreaded computations.  If there are
     * updates concurrent with this method, the returned value is
     * <em>not</em> guaranteed to be the final value occurring before
     * the reset.
     *
     * @return the sum
     */
    public long sumThenReset() {
        Cell[] as = cells; Cell a;
        long sum = base;
        base = 0L;
        if (as != null) {
            for (int i = 0; i < as.length; ++i) {
                if ((a = as[i]) != null) {
                    sum += a.value;
                    a.value = 0L;
                }
            }
        }
        return sum;
    }
    略...
}

posted @ 2023-06-04 16:24  bxdblog  阅读(7)  评论(0编辑  收藏  举报