1.什么是原子操作类

就是我们一般在使用程序更新一个变量,当前变量i=1,如果两个线程都对齐i++,由于线程的竞争,可能结果为2就不是3了。而要保证线程的同步性,那么我们以前的解决办法肯定是加synchrnized关键字来保证只能有一个线程来更新操作。java提供了更高效的类:原子操作类。分为:基本类型的原子更新、数组类型的原子更新、引用类型的原子更新、属性的原子更新。

2.原子更新基本类型类

     ---  AtomicBoolean:原子更新布尔值类型。

     ---  AtomicInteger:原子更新整型。

     ---  AtomicLong:原子更新长整型。

实现:


public class AtomicIntegerTest {
	
	public static void main(String[] args) {
		AtomicInteger ai= new AtomicInteger(2);
		int initalVal=ai.get();
		System.out.println("初始化当前值a为:"+initalVal);
		System.out.println("当前值a+3="+ai.addAndGet(-3));
		ai.getAndIncrement();
		int nextVal=ai.get();
		System.out.println("加1后的当前值为:"+nextVal);
		System.out.println("更新值是否等于预期值:"+ai.compareAndSet(nextVal, 10));
		int updateVal=ai.get();
		System.out.println("更新后的值:"+updateVal);
	}
}

结果:

初始化当前值a为:2
当前值a+3=-1
加1后的当前值为:0
更新值是否等于预期值:true
更新后的值:10
注意:getAndIncrement();方法的返回值为加1之前的值。

java 如何定义原子变量 java原子性操作有哪些_System

java 如何定义原子变量 java原子性操作有哪些_数组_02

java 如何定义原子变量 java原子性操作有哪些_System_03

3.原子更新数组

AtomicIntegerArray:原子更新整型数组里的元素。

AtomicLongArray:原子更新整型数组里的元素。

AtomicReferenceArray:原子更新引用类型数组里元素。

其实方法和上面原子更新基本类型大多都一样。

实现:


public class AtomicIntegerArrayTest {
	public static void main(String[] args) {
		int[] value=new int[]{1,2};
		AtomicIntegerArray aia=new AtomicIntegerArray(value);
		aia.getAndSet(0, 5);
		System.out.println("数组下标0对应的原子值更新为:"+aia.get(0));
		System.out.println("原数组的值:"+value[0]);
	}
}

结果:

数组下标0对应的原子值更新为:5
原数组的值:1

java 如何定义原子变量 java原子性操作有哪些_System_04

4.原子更新引用类型

AtomicReference:原子更新引用类型。

AtomicReferenceFieldUpdater:原子更新引用类型里的字段。

AtomicMarkableReference:原子更新带有标记位的引用类型。可以原子更新一个布尔类型的标记位和引用类型。

其实方法和上面原子更新基本类型大多都一样。

实现:


public class AtomicReferenceTest {
	public static void main(String[] args) {
		AtomicReference<User> ar=new AtomicReference<User>();
		User user=new User("张三",19);
		ar.set(user);
		System.out.println("当前原子姓名:"+ar.get().getName()+" ,当前原子年龄:"+ar.get().getAge());
		User updateUser=new User("李四",29);
		ar.set(updateUser);
		System.out.println("更新原子姓名:"+ar.get().getName()+" ,更新原子年龄:"+ar.get().getAge());
	}
}
class User{
	private String name;
	private int age;
	public User(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

结果:

当前原子姓名:张三 ,当前原子年龄:19
更新原子姓名:李四 ,更新原子年龄:29

java 如何定义原子变量 java原子性操作有哪些_数组_05

5.原子更新字段类

AtomicIntegerFieldUpdater:原子更新整型的字段的更新器。

AtomicLongFieldUpdater:原子更新长整型字段的更新器。

AtomicStampedReference:原子更新带有版本号的引用类型。使用这个类可以将那个整数值与引用关联,可以用来以原子的方式来更新数据和数据的版本号,可以解决原子更新可能出现的ABA问题。

其实方法和上面原子更新基本类型大多都一样。

实现:


public class AtomicIntegerFieldUpdaterTest {
	public static void main(String[] args) {
		AtomicIntegerFieldUpdater<MyUser> aifu=AtomicIntegerFieldUpdater.newUpdater(MyUser.class, "age");
		MyUser myUser=new MyUser("张三",20);
		System.out.println("此时原子值为:"+aifu.getAndIncrement(myUser));
          System.out.println("更新原子值为:"+aifu.get(myUser));
	}
}
class MyUser{
	private String name;
	public volatile int age;
	public MyUser(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

结果:

此时原子值为:20
更新原子值为:21

解释:原子更新字段首先需要创建一个更新器,并且还得设置需要更新的类和属性。用作更新的属性需要使用volatile、public字段修饰。