1、原子类AtomicInteger的API讲解
package day05.part1;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 原子类AtomicInteger的API讲解
* @author xzq
*/
public class AtomicTest01 {
public static void main(String[] args) {
/*
*空参数 默认为0
*/
AtomicInteger atmInteger=new AtomicInteger();
/*
* 注意下面的API都是线程不安全的,只用于初始化使用
* 在多线程共享数据时不要使用
*/
System.out.println("获取值:"+atmInteger.get());
atmInteger=new AtomicInteger(5);
System.out.println("获取值:"+atmInteger.get());
atmInteger.set(10);
System.out.println("获取值:"+atmInteger.get());
/*
* 以下方法能保证多线程情况下的原子性
*/
int getAndAddResult = atmInteger.getAndAdd(10);//a=a+10
System.out.println("自增后的返回值:"+getAndAddResult);
System.out.println("当前类中的值:"+atmInteger.get());
//没有提供自减指定值的方法所以用这样的方式实现自减
atmInteger.getAndAdd(-5);//a=a-5
atmInteger.decrementAndGet();//a--
/*
* 原子赋值操作,必须传当前最新读到的预期值,
* 且必须为int类型
*/
atmInteger.compareAndSet(14, 20);//当前值是14 如果下面判断也是14 就会被更新为20
/* atmInteger.compareAndSet(15, 20);
atmInteger.compareAndSet(10, 20);*/
System.out.println("当前类中的值:"+atmInteger);
}
}
2、原子类AtomicBoolean的API讲解
package day05.part1;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* 原子类AtomicBoolean的API讲解
* @author xzq
*/
public class AtomicTest02 {
public static void main(String[] args) {
AtomicBoolean atmBoolean=new AtomicBoolean();
/*
* 注意下面的API都是线程不安全的,只用于初始化使用
* 在多线程共享数据时不要使用
* 不赋值默认是false
*/
atmBoolean.set(true);
//要赋值的时候用这个API,可以保证本赋值操作的原子性
// atmBoolean.getAndSet(true);
/*
* 和AtomicInteger一样,必须传一个预期的值,如果预期的值
* 和当前类中的值不同(就是在赋值过程中有被其它线程打断更改的情况)
* 那么就不进行赋值操作,保留原值。
*/
atmBoolean.compareAndSet(true, true);
System.out.println("当前类中的值:"+atmBoolean);
}
}
3、原子类AtomicLong的API讲解
package day05.part1;
import java.util.concurrent.atomic.AtomicLong;
/**
* 原子类AtomicLong的API讲解
* CPU有32位的,也有64位的,
* 32位的CPU代表依编指令一次可以处理32 bit(位)的数据 4个字节
* 64位的CPU代表汇编指令一次可以处理64 bit(位)的数据 8个字节
*
* int 是等于4byte(4个字节)= 32位
* long 是等于8byte(8个字节)=64位
* 如果是32位的CPU,那么处理long型的数据是先读高位,再读低位分两次读取
* 为了保证2次读取的原子性,那么就在AtomicLong中加了一个对32位CPU的支持
* @author xzq
*/
public class AtomicTest03 {
public static void main(String[] args) {
AtomicLong atmLong=new AtomicLong();
/*
* 注意下面的API都是线程不安全的,只用于初始化使用
* 在多线程共享数据时不要使用
*/
atmLong.set(30L);
//要赋值的时候用这个API,可以保证本赋值操作的原子性
atmLong.getAndSet(35L);
/*
* 和AtomicInteger一样,必须传一个预期的值,如果预期的值
* 和当前类中的值不同(就是在赋值过程中有被其它线程打断更改的情况)
* 那么就不进行赋值操作,保留原值。
*/
atmLong.compareAndSet(31L, 36L);
// atmLong.compareAndSet(30L, 35L);
System.out.println("当前类中的值:"+atmLong);
}
}
4、原子类AtomicReference的API讲解
package day05.part1;
import day05.bean.Person;
import java.util.concurrent.atomic.AtomicReference;
/**
* 原子类AtomicReference的API讲解
* @author xzq
*/
public class AtomicTest04 {
public static void main(String[] args) {
AtomicReference<Person> atmRef=new AtomicReference<>();
/*
* 注意下面的API都是线程不安全的,只用于初始化使用
* 在多线程共享数据时不要在线程内部去使用
*/
Person p=new Person("Peter",115,"北京");
/*
* 对于没有重写hashCode的类的实例那么它的hashCode就是它的引用地址
* 这里用int数组为例,证明对象的引用是用一个int型的变量来存储的
*/
int[] arr=new int[10];
int refInt= arr.hashCode();
System.out.println("数组对象的引用是:"+arr);
System.out.println("数组对象的引用,用int类型表示为:"+refInt);
atmRef.set(p);
//要赋值的时候用这个API,可以保证本赋值操作的原子性
Person toUpdateP = new Person("Cat", 38, "北京");
atmRef.getAndSet(toUpdateP);
/*
* 和AtomicInteger一样,必须传一个预期的值,如果预期的值
* 和当前类中的值不同(就是在赋值过程中有被其它线程打断更改的情况)
* 那么就不进行赋值操作,保留原值。
* 对比的是应用 而不是对象内容
*/
boolean casIsSuccess = atmRef.compareAndSet(new Person("Cat", 38, "杭州"), toUpdateP);
// boolean casIsSuccess = atmRef.compareAndSet(p, toUpdateP);
// System.out.println("CAS操作是否成功:"+casIsSuccess);
System.out.println("当前类中的值:"+atmRef);
/*
* 如果要实现原子写操作,那么自己手写一个原子类
* 我已经写好了,请看MyAtomicReference
*/
}
}
5、ABA问题
package day05.part1;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;
/**
* ABA问题
* @author xzq
*/
public class AtomicTest05 {
public static void main(String[] args) {
final AtomicInteger atmInteger=new AtomicInteger(1);
new Thread("线程1:"){
@Override
public void run() {
String threadName = Thread.currentThread().getName();
//这里读到的是1
int getValue = atmInteger.get();
System.out.println(threadName+"读到的数据是:"+getValue);
//在进行CAS算法的原子操作之前阻塞1秒方便其它线程进行打断后操作
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
//进行CAS算法的原子操作将1 ---->2
if(atmInteger.compareAndSet(getValue, 5)){
System.out.println(threadName+"把:"+getValue+"更新为 5成功!");
}else{
System.out.println(threadName+"更新操作失败!");
}
}
}.start();
new Thread("线程2:"){
@Override
public void run() {
String threadName = Thread.currentThread().getName();
//这里读到的是1
int getValue = atmInteger.get();
System.out.println(threadName+"读到的数据是:"+getValue);
//进行CAS算法的原子操作将1 ---->2
if(atmInteger.compareAndSet(getValue, 2)){
System.out.println(threadName+"把:"+getValue+"更新为 2");
getValue= atmInteger.get();
System.out.println(threadName+"读到的数据是:"+getValue);
//进行CAS算法的原子操作将2 ---->1
if(atmInteger.compareAndSet(getValue, 1)){
System.out.println(threadName+"把:"+getValue+"更新为 1成功!");
}
}
}
}.start();
}
}
6、解决ABA问题1
package day05.part1;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;
import java.util.concurrent.locks.LockSupport;
/**
* 解决ABA问题
* @author xzq
*/
public class AtomicTest06_1 {
public static void main(String[] args) {
final AtomicStampedReference<Integer> atmStaRef=new AtomicStampedReference<Integer>(1, 0);
new Thread("线程1:"){
@Override
public void run() {
String threadName = Thread.currentThread().getName();
//这里读到的是1
int getValue = atmStaRef.getReference();
int stamp = atmStaRef.getStamp();
System.out.println(threadName+"读到的数据是:"+getValue+",版本号是:"+stamp);
//在进行CAS算法的原子操作之前阻塞1秒方便其它线程进行打断后操作
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
if(atmStaRef.compareAndSet(getValue, 2, stamp, stamp+1)){
System.out.println(threadName+"把:"+getValue+"更新为 5成功!");
}else{
System.out.println(threadName+"更新操作失败!");
}
}
}.start();
new Thread("线程2:"){
@Override
public void run() {
String threadName = Thread.currentThread().getName();
//这里读到的是1
int getValue = atmStaRef.getReference();
int stamp = atmStaRef.getStamp();
System.out.println(threadName+"读到的数据是:"+getValue);
//进行CAS算法的原子操作将1 ---->2
if(atmStaRef.compareAndSet(getValue, 2,stamp,stamp+1)){
System.out.println(threadName+"把:"+getValue+"更新为 2");
getValue= atmStaRef.getReference();
System.out.println(threadName+"读到的数据是:"+getValue);
//进行CAS算法的原子操作将2 ---->1
if(atmStaRef.compareAndSet(getValue, 1,stamp,stamp+1)){
System.out.println(threadName+"把:"+getValue+"更新为 1成功!");
}
}
}
}.start();
}
}
6、解决ABA问题2
package day05.part1;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicMarkableReference;
import java.util.concurrent.locks.LockSupport;
/**
* 解决ABA问题
* @author xzq
*/
public class AtomicTest06_2 {
public static void main(String[] args) {
final AtomicMarkableReference<Integer> atmMarRef=new AtomicMarkableReference<Integer>(1, false);
new Thread("线程1:"){
@Override
public void run() {
String threadName = Thread.currentThread().getName();
//这里读到的是1
int getValue = atmMarRef.getReference();
boolean marked = atmMarRef.isMarked();
System.out.println(threadName+"读到的数据是:"+getValue+",标记是:"+marked);
//在进行CAS算法的原子操作之前阻塞1秒方便其它线程进行打断后操作
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
if(atmMarRef.compareAndSet(getValue, 2, marked, true)){
System.out.println(threadName+"把:"+getValue+"更新为 5成功!");
}else{
System.out.println(threadName+"更新操作失败!");
}
}
}.start();
new Thread("线程2:"){
@Override
public void run() {
String threadName = Thread.currentThread().getName();
//这里读到的是1
int getValue = atmMarRef.getReference();
boolean marked = atmMarRef.isMarked();
System.out.println(threadName+"读到的数据是:"+getValue+",标记是:"+marked);
//进行CAS算法的原子操作将1 ---->2
if(atmMarRef.compareAndSet(getValue, 2,marked,!marked)&&atmMarRef.attemptMark(2, marked)){
System.out.println(threadName+"把:"+getValue+"更新为 2");
//重置marked
getValue= atmMarRef.getReference();
marked=atmMarRef.isMarked();
System.out.println(threadName+"读到的数据是:"+getValue);
//进行CAS算法的原子操作将2 ---->1
if(atmMarRef.compareAndSet(getValue, 1,marked,!marked)){
System.out.println(threadName+"把:"+getValue+"更新为 1成功!");
}
}
}
}.start();
}
}
7、解决ABA问题 原子类AtomicStampedReference的API讲解
package day05.part1;
import java.util.concurrent.atomic.AtomicStampedReference;
/**
* 解决ABA问题 原子类AtomicStampedReference的API讲解
*
* @author xzq
*/
public class AtomicTest07 {
public static void main(String[] args) {
AtomicStampedReference<Integer> atmStaRef = new AtomicStampedReference<Integer>(40, 0);
int stamp = atmStaRef.getStamp();
boolean casIsSuccess = atmStaRef.compareAndSet(40, 41, stamp, stamp + 1);
// boolean casIsSuccess =atmStaRef.compareAndSet(40, 41,1 , stamp+1);
System.out.println("CAS操作是否成功:"+casIsSuccess);
System.out.println("当前类中的值:" + atmStaRef.getReference());
}
}
8、解决ABA问题 原子类AtomicMarkableReference的API讲解
package day05.part1;
import java.util.concurrent.atomic.AtomicMarkableReference;
/**
* 解决ABA问题 原子类AtomicMarkableReference的API讲解
*
* @author xzq
*/
public class AtomicTest08 {
public static void main(String[] args) {
AtomicMarkableReference<Integer> atmMarRef=new AtomicMarkableReference<Integer>(50, false);
boolean marked = atmMarRef.isMarked();
boolean casIsSuccess = atmMarRef.compareAndSet(50, 51, marked, !marked);
// boolean casIsSuccess = atmMarRef.compareAndSet(50, 51, true, !marked);
System.out.println("CAS操作是否成功:"+casIsSuccess);
System.out.println("当前类中的值:" + atmMarRef.getReference());
}
}
9、原子类AtomicIntegerArray、AtomicLongArray和 AtomicReferenceArray的API讲解
package day05.part1;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.concurrent.atomic.AtomicLongArray;
import java.util.concurrent.atomic.AtomicReferenceArray;
/**
* 原子类AtomicIntegerArray、AtomicLongArray和
* AtomicReferenceArray的API讲解
*
* @author xzq
*/
public class AtomicTest09 {
public static void main(String[] args) {
// AtomicIntegerArray atmIntArr=new AtomicIntegerArray(5);
AtomicIntegerArray atmIntArr=new AtomicIntegerArray(new int[]{1,2,3,4,5});
AtomicLongArray atmLongArr=new AtomicLongArray(6);
AtomicReferenceArray<String> atmRefArr=new AtomicReferenceArray<>(7);
// atmIntArr.set(0, 11);
// atmIntArr.getAndSet(0, 12);
/*
* 传入一个期望值,如果当前读到的值和预期值一样就更新
* 不一样就什么也不做
* 1是下标为1的数字 如果为2 修改为12
*/
boolean casIsSuccess = atmIntArr.compareAndSet(1, 2, 12);
// boolean casIsSuccess = atmIntArr.compareAndSet(1, 22, 12);
//-------------AtomicIntegerArray的打印
System.out.println("整型数组长度为:"+atmIntArr.length());
System.out.println("整型数组第1个元素为:"+atmIntArr.get(0));
System.out.println("整型数组第2个元素为:"+atmIntArr.get(1));
//-------------AtomicLongArray的打印
atmLongArr.getAndSet(5, 6);
System.out.println("长整型数组长度为:"+atmLongArr.length());
System.out.println("长整型第1个元素为:"+atmLongArr.get(0));
System.out.println("长整型第6个元素为:"+atmLongArr.get(5));
//-------------AtomicReferenceArray的打印
atmRefArr.getAndSet(6, "Peter");
System.out.println("引用类型数组长度为:"+atmRefArr.length());
System.out.println("引用类型第1个元素为:"+atmRefArr.get(0));
System.out.println("引用类型第7个元素为:"+atmRefArr.get(6));
System.out.println("CAS操作是否成功:"+casIsSuccess);
// System.out.println("当前类中的值:" + atmMarRef.getReference());
}
}