compare and swap的缩写,中文翻译成比较并交换,实现并发算法时常用到的一种技术。它包含三个操作数——内存位置、预期原值及更新值。
/**
* ABA问题,两边没有问题,但中间被修改过。
*/
public class ABATest01 {
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(10);//初始值10
new Thread(()->{
System.out.println("A: "+atomicInteger.get());
atomicInteger.compareAndSet(10,2022); //将值更新为2022
System.out.println("B: "+atomicInteger.get());
atomicInteger.compareAndSet(2022,10); //将值更新为10
System.out.println("A: "+atomicInteger.get());
},"t1").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
System.out.println("A: "+atomicInteger.get());//10值没变
atomicInteger.compareAndSet(10,2022);//将值更新为2022
System.out.println("B: "+atomicInteger.get());//2022
//虽然更新成功,但中间却被修改过
},"t1").start();
}
}
/**
* 解决:版本号,时间戳
*/
public class ABATest02 {
static AtomicStampedReference<Integer> stampedReference = new AtomicStampedReference<Integer>(10,1);
public static void main(String[] args) {
new Thread(()->{
System.out.println("t1 第一次:"+stampedReference.getReference()+"\t"+stampedReference.getStamp());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
stampedReference.compareAndSet(10,100,stampedReference.getStamp(),stampedReference.getStamp()+1);
System.out.println("t1 第一次修改完:"+stampedReference.getReference()+"\t"+stampedReference.getStamp());
stampedReference.compareAndSet(100, 10, stampedReference.getStamp(), stampedReference.getStamp()+1);
System.out.println("t1 第二次修改完:"+stampedReference.getReference()+"\t"+stampedReference.getStamp());
},"t1").start();
new Thread(()->{
int stamp=stampedReference.getStamp();
System.out.println("t2 第一次:"+stampedReference.getReference()+"\t"+stamp);
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
boolean b = stampedReference.compareAndSet(100, 2022, stamp, stamp + 1);
System.out.println("t2 第一次修改情况:"+b);
System.out.println("t2 第一次修改完:"+stampedReference.getReference()+"\t"+stampedReference.getStamp());
},"t2").start();
}
}
/**
* 利用CAS原子引用完成自旋锁
*/
public class SpinLockTest {
AtomicReference<Thread> atomicReference=new AtomicReference<Thread>();
public void lock(){//加锁
Thread thread = Thread.currentThread();
while (!atomicReference.compareAndSet(null,thread)){}
}
public void unlock(){//解锁
Thread thread = Thread.currentThread();
while (!atomicReference.compareAndSet(thread,null)){}
}
public static void main(String[] args) {
SpinLockTest spinLock = new SpinLockTest();
new Thread(()->{
spinLock.lock();
System.out.println("t1 come in...");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
spinLock.unlock();
System.out.println("t1 unlock in...");
},"t1").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
spinLock.lock();
System.out.println("t2 come in...");
spinLock.unlock();
System.out.println("t2 unlock in...");
},"t2").start();
}
}
java.util.concurrent.atomic 包下的类
AtomicLong
public final int get() //获取当前的值
public final int getAndSet(int newValue)//获取当前的值,并设置新的值
public final int getAndIncrement()//获取当前的值,并自增
public final int getAndDecrement() //获取当前的值,并自减
public final int getAndAdd(int delta) //获取当前的值,并加上预期的值
boolean compareAndSet(int expect, int update) //如果输入的数值等于预期值,则以原子方式将该值设置为输入值(update)
AtomicIntegerArray
AtomicLongArray
AtomicReferenceArray
public class AtomicIntegerArrayTest
{
public static void main(String[] args)
{
AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(new int[5]);
//AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(5);
//AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(new int[]{1,2,3,4,5});
for (int i = 0; i <atomicIntegerArray.length(); i++) {
System.out.println(atomicIntegerArray.get(i));
}
System.out.println();
System.out.println();
System.out.println();
int tmpInt = 0;
tmpInt = atomicIntegerArray.getAndSet(0,1122);
System.out.println(tmpInt+"\t"+atomicIntegerArray.get(0));
atomicIntegerArray.getAndIncrement(1);
atomicIntegerArray.getAndIncrement(1);
tmpInt = atomicIntegerArray.getAndIncrement(1);
System.out.println(tmpInt+"\t"+atomicIntegerArray.get(1));
}
}
更新的对象属性必须使用 public volatile 修饰符。
因为对象的属性修改类型原子类都是抽象类,所以每次使用都必须使用静态方法newUpdater()创建一个更新器,并且需要设置想要更新的类和属性。
/**
* 原子 数值类型 属性字段修改
*/
public class AtomicIntegerFieldUpdaterTest {
private static final int SIZE=50;
public static void main(String[] args) {
Account account = new Account();
CountDownLatch countDownLatch = new CountDownLatch(SIZE);
for (int i = 0; i < SIZE; i++) {
new Thread(()->{
try {
for (int j = 0; j <1000 ; j++) {
account.transfer(account);
}
} finally {
countDownLatch.countDown();
}
}).start();
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(account.money);
}
}
class Account{
public volatile int money=0;
AtomicIntegerFieldUpdater<Account> updater=
AtomicIntegerFieldUpdater.newUpdater(Account.class,"money");
public void transfer(Account account){
updater.incrementAndGet(account);
}
}
**
* 高性能 累加器
*/
public class LongAdderTest {
public static void main(String[] args) throws InterruptedException {
LongAdder longAdder = new LongAdder();
CountDownLatch countDownLatch = new CountDownLatch(1000);
for (int i = 0; i <1000 ; i++) {
new Thread(()->{
longAdder.increment();
countDownLatch.countDown();
}).start();
}
countDownLatch.await();
longAdder.decrement();
System.out.println(longAdder.sum());
}
}
/**
* 高性能 计算
*/
public class LongAccumulatorTest {
public static void main(String[] args) throws InterruptedException {
LongAccumulator accumulator = new LongAccumulator((x,y)->x+y,0);
CountDownLatch countDownLatch = new CountDownLatch(1000);
for (int i = 0; i <1000 ; i++) {
new Thread(()->{
accumulator.accumulate(1);
countDownLatch.countDown();
}).start();
}
countDownLatch.await();
System.out.println(accumulator.get());
}
}