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;
}
略...
}