目录
1.4 CAS解决ABA:AtmoicStampRefenence
2 Atomic:(以AtomicInteger为例)2.1 AtomicInteger解决原子性问题代码:
3.1 AtmoicStampRefenence解决ABA实例代码:
4. AtomicXXFieldUpdater(以AtomicIntegerFieldUpdater为例)
4.1 AtomicIntegerFieldUpdater 局限
4.1.1 不能访问对象的私有属性;4.1.2 访问的对象为null;4.1.3 field类型不匹配4.1.4 field必须是voletile
4.2 AtomicIntegerFieldUpdater使用场景:
4.2.1 让对象的属性操作具备原子性;4.2.2 保证对象的某个属性的原子性,而不是整个对象,减少内存消耗;4.2.3 避免使用Synchronized等重量级锁
4.3 AtomicIntegerFieldUpdater实例代码
4.4 AtomicIntegerFieldUpdater源码
1CAS
1.1 CAS定义
定义:compare and swap比较再交换
1.2 CAS优势
优势:CPU级别的同步指令,对于应用来说,相当于无锁。
1.3 CAS局限
局限:无法解决ABA问题。
1.4 CAS解决ABA:AtmoicStampRefenence
2 Atomic:(以AtomicInteger为例)
2.1 AtomicInteger解决原子性问题代码:
AtomicInteger是基于CAS,无法解决ABA问题
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
public class AtomicTest {
public static int version = 1;
public static int num = 1;
public static volatile int state = 0;
public static void main(String[] args) throws Exception {
//原子性:一个操作或者多个操作要么全部执行并且过程中不被打断,要么全部不执行
//解决原子性问题
AtomicInteger atomicInteger2 = new AtomicInteger(0);
new Thread(() -> {
for (int i = 0; i < 100; i++) {
atomicInteger2.getAndAdd(1);
atomicInteger2.getAndAdd(-1);
atomicInteger2.getAndAdd(1);
System.out.println(Thread.currentThread().getName() + ":" + atomicInteger2.get());
}
}, "thread1").start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
atomicInteger2.getAndAdd(1);
System.out.println(Thread.currentThread().getName() + ":" + atomicInteger2.get());
}
}, "thread2").start();
Thread.sleep(2000);
//volatile修饰的变量无法解决原子性问题;中间state可能会出现同值问题(多运行几次)
new Thread(() -> {
try{
for (int i = 0; i < 100; i++) {
state++;
state--;
state++;
System.out.println(Thread.currentThread().getName() + ":" + state);
}
}catch (Exception e){
}
}, "thread3").start();
new Thread(() -> {
try{
for (int i = 0; i < 100; i++) {
state++;
System.out.println(Thread.currentThread().getName() + ":" + state);
}
}catch (Exception e){
}
}, "thread4").start();
2.2 AtomicInteger源码
//AtomicInteger源码
//构造方法
private volatile int value;
public AtomicInteger(int initialValue) {
value = initialValue;
}
//getAndSet 基于CAS机制
public final int getAndSet(int newValue) {
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
3 AtmoicStampRefenence
3.1 AtmoicStampRefenence解决ABA实例代码:
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
public class AtomicTest {
public static int version = 1;
public static int num = 1;
public static volatile int state = 0;
public static void main(String[] args) throws Exception {
//无法解决ABA问题
AtomicInteger atomicInteger = new AtomicInteger(1);
new Thread(()->{
try{
TimeUnit.SECONDS.sleep(2);
atomicInteger.getAndAdd(1);
System.out.println(Thread.currentThread().getName()+":"+atomicInteger.get());
}catch (Exception e){
}
},"thread1").start();
new Thread(()->{
atomicInteger.getAndAdd(1);
System.out.println(Thread.currentThread().getName()+":"+atomicInteger.get());
atomicInteger.getAndAdd(-1);
System.out.println(Thread.currentThread().getName()+":"+atomicInteger.get());
},"thread2") .start();
//能够解决ABA问题
AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(num,version);
int stamp = atomicStampedReference.getStamp();
Thread.sleep(1000);
new Thread(()->{
try{
try{
TimeUnit.SECONDS.sleep(2);
boolean flag = atomicStampedReference.compareAndSet(num,++num,stamp,stamp+5);
System.out.println(Thread.currentThread().getName()+"的值:"+atomicStampedReference.getReference());
System.out.println(Thread.currentThread().getName()+"的版本:"+atomicStampedReference.getStamp());
System.out.println(flag);
}catch (Exception e){
}
}catch (Exception e){
}
},"thread1").start();
new Thread(()->{
atomicStampedReference.compareAndSet(num,++num,version,++version);
System.out.println(Thread.currentThread().getName()+"的版本:"+atomicStampedReference.getStamp());
System.out.println(Thread.currentThread().getName()+"的值:"+atomicStampedReference.getReference());
atomicStampedReference.compareAndSet(num,--num,version,++version);
System.out.println(Thread.currentThread().getName()+"的值:"+atomicStampedReference.getReference());
System.out.println(Thread.currentThread().getName()+"的版本:"+atomicStampedReference.getStamp());
},"thread2") .start();
3.2 AtmoicStampRefenenc源码
//构造
private volatile Pair<V> pair;
public AtomicStampedReference(V initialRef, int initialStamp) {
pair = Pair.of(initialRef, initialStamp);
}
private static class Pair<T> {
final T reference;
final int stamp;
private Pair(T reference, int stamp) {
this.reference = reference;
this.stamp = stamp;
}
static <T> Pair<T> of(T reference, int stamp) {
return new Pair<T>(reference, stamp);
}
}
//compareAndSet
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
Pair<V> current = pair;
return
expectedReference == current.reference &&
expectedStamp == current.stamp &&
((newReference == current.reference &&
newStamp == current.stamp) ||
casPair(current, Pair.of(newReference, newStamp)));
}
4. AtomicXXFieldUpdater(以AtomicIntegerFieldUpdater为例)
4.1 AtomicIntegerFieldUpdater 局限
4.1.1 不能访问对象的私有属性;
4.1.2 访问的对象为null;
4.1.3 field类型不匹配
4.1.4 field必须是voletile
4.2 AtomicIntegerFieldUpdater使用场景:
4.2.1 让对象的属性操作具备原子性;
4.2.2 保证对象的某个属性的原子性,而不是整个对象,减少内存消耗;
4.2.3 避免使用Synchronized等重量级锁
4.3 AtomicIntegerFieldUpdater实例代码
import lombok.Data;
@Data
public class Student {
volatile int age;
//private int age; 不能是私有的,且必须是volatile修饰
private String name;
}
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
public class AtomicTest {
public static void main(String[] args) throws Exception {
//确保对象某个属性原子性
AtomicIntegerFieldUpdater<Student> atomicIntegerFieldUpdater = AtomicIntegerFieldUpdater.newUpdater(Student.class,"age");
//对象不能为null,变量属性不能为私有,必须由volatile修饰,变量类型与AtomicXX对应的类型要一致
Student student = new Student();
student.setAge(1);
atomicIntegerFieldUpdater.getAndAdd(student,1);
System.out.println(atomicIntegerFieldUpdater.get(student));
}
}
4.4 AtomicIntegerFieldUpdater源码
//创建 基于反射
public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass,
String fieldName) {
return new AtomicIntegerFieldUpdaterImpl<U>
(tclass, fieldName, Reflection.getCallerClass());
}
AtomicIntegerFieldUpdaterImpl(final Class<T> tclass,
final String fieldName,
final Class<?> caller) {
final Field field;
final int modifiers;
try {
field = AccessController.doPrivileged(
new PrivilegedExceptionAction<Field>() {
public Field run() throws NoSuchFieldException {
return tclass.getDeclaredField(fieldName);
}
});
modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers);
ClassLoader cl = tclass.getClassLoader();
ClassLoader ccl = caller.getClassLoader();
if ((ccl != null) && (ccl != cl) &&
((cl == null) || !isAncestor(cl, ccl))) {
sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
}
} catch (PrivilegedActionException pae) {
throw new RuntimeException(pae.getException());
} catch (Exception ex) {
throw new RuntimeException(ex);
}
if (field.getType() != 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) &&
tclass.isAssignableFrom(caller) &&
!isSamePackage(tclass, caller))
? caller : tclass;
this.tclass = tclass;
this.offset = U.objectFieldOffset(field);
}
//getAndAdd
public int getAndAdd(T obj, int delta) {
int prev, next;
do {
prev = get(obj);
next = prev + delta;
} while (!compareAndSet(obj, prev, next));
return prev;
}
public final int get(T obj) {
accessCheck(obj);//判断类型是否匹配
return U.getIntVolatile(obj, offset);//基于CAS获取
}
private final void accessCheck(T obj) {
if (!cclass.isInstance(obj))
throwAccessCheckException(obj);
}