文章目录

一,java中的原子操作类型

jdk1.5开始提供了Atomic包,这个包中的原子操作类提供了一种用法简单,性能高效,线程安全的更新一个变量的方式

二,原子更新基本类型

该类用于原子的更新基本类型:

  • AtomicInteger
  • AtomicBoolean
  • AtomicLong
/**
* @Description: 原子更新基本类型
* @Author: Kevin
* @CreateDate: 2019/7/1 21:34
* @UpdateUser: Kevin
* @UpdateDate: 2019/7/1 21:34
* @UpdateRemark: 修改内容
* @Version: 1.0
*/
public class AtomicIntergerTest {

static AtomicInteger atomicInteger = new AtomicInteger(1);

public static void main(String[] args) {
//原子的方式增加指定的值
System.out.println("--------->" + atomicInteger.addAndGet(1));
//compareAndSet(int expect,int update)如果expect = atomicInteger.get() 则将该atomicInteger.get()设置为update
System.out.println("--------->"+atomicInteger.compareAndSet(1,2)+atomicInteger.get());
//自增1,返回的是自增前的值
System.out.println("--------->"+atomicInteger.getAndIncrement());
//自减1,返回的是自减前的值
System.out.println("--------->"+atomicInteger.getAndDecrement());
//延时更新
atomicInteger.lazySet(1);
}
}

1.原子更新原理

1.getAndIncrement()原理

注意点:

  • atomicInteger.compareAndSet(current,next)

这是进行原子更新操作的重点,检查当前原子值是否等于current(期望值),如果相等,就是当前原子值没有被其他线程修改,可以进行更新操作

/**
* getAndIncrement()原理
* @return
*/
public static int getAndIncrement(){
for(;;){
//获取当前原子值
int current = get();
//自增
int next = current+1;
//如果当前原子值 == current 就将当前原子值设置为next
if(atomicInteger.compareAndSet(current,next)){
//返回自增前原子值
return current;
}
}
}

2.UnSafe

作用

执行低级别,不安全的操作

使用

在java程序中无法直接使用unsafe,其构造方法是私有的,我们只能通过Unsafe的getUnsafe()方法获取该类的对象:

private static final Unsafe unsafe = Unsafe.getUnsafe();

相关具体使用:

  • 修改内存
    unsafe通过相关的putxxx 和getxxx方法来修改内存和获取内存中的值
  • 在非java堆中分配内存
    Unsafe类通过allocateMemory(long)方法分配的内存,不受Integer.MAX_VALUE的限制,并且分配在非堆内存,使用它时,需要非常谨慎,该部分内存需要手动回收,否则会产生内存泄露
  • CAS
    下面提到

3.CAS

CAS,Compare and Swap即比较并交换,设计并发算法时常用到的一种技术,java.util.concurrent包全完建立在CAS之上,没有CAS也就没有此包,可见CAS的重要性。

Unsafe类中提供了compareAndSwapObject()、compareAndSwapInt()和compareAndSwapLong()这三个方法用来实现对应的CAS原子操作。在Java的并发编程中用到的CAS操作都是调用的Unsafe类的相关方法。

unsafe中的CAS

public final native boolean compareAndSwapObject(Object o,Long offset,Object expected,Object x);

public final native boolean compareAndSwapInt(Object o,Long offset,Object expected,Object x);

public final native boolean compareAndSwapLong(Object o,Long offset,Object expected,Object x);

CAS操作原理

CAS有三个操作数:内存值V、旧的预期值A、要修改的值B,当且仅当预期值A和内存值V相同时,将内存值修改为B并返回true,否则,即内存值和当前预期值不等时,则可能是其他线程修改了当前内存值,造成线程不安全的现象,所以这时。CAS什么都不做并返回false。

三,原子更新引用类型

原子更新基本类型只能更新一个变量,如果要原子更新多个变量,就需要使用这个原子更新引用类型提供的类

  • AtomicReference 原子更新引用类型
  • AtomicReferenceFieldUpdater 原子更新引用类型里的字段
  • AtomicMarkableRefrence 原子更新带有标记位的引用类型

使用

/**
* @Auther: Kevin
* @Date:
* @ClassName:AtomicReferenceTest
* @Description: TODO
*/
public class AtomicReferenceTest {

public static AtomicReference<User> atomicReference = new AtomicReference<>();

public static void main(String[] args) {
User user = new User("kevin",15);
atomicReference.set(user);
User updateUser = new User("newKevin",20);
atomicReference.compareAndSet(user,updateUser);
System.out.println("--------->"+atomicReference.get().getName());
System.out.println("--------->"+atomicReference.get().getAge());
}

static class User{
private String name;
private int age;

public User(String name, int age) {
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;
}
}
}

四,原子更新类中字段

如果需要原子地更新某个类里的某个字段时,需要使用原子更新字段类:

  • AtomicIntegerFieldUpdater
  • AtomicLongFieldUpdater
  • AtomicStampedFieldUpdater
/**
* @Auther: Kevin
* @Date:
* @ClassName:AtomicIntegerFiledUpdaterTest
* @Description: TODO
*/
public class AtomicIntegerFiledUpdaterTest {


public static AtomicIntegerFieldUpdater<AtomicIntegerFiledUpdaterTest.User> atomicIntegerFieldUpdater = AtomicIntegerFieldUpdater.newUpdater(AtomicIntegerFiledUpdaterTest.User.class,"age");

public static void main(String[] args) {
User user = new User("kevin",20);
System.out.println("-------->"+atomicIntegerFieldUpdater.getAndIncrement(user));
System.out.println("--------->"+atomicIntegerFieldUpdater.get(user));
}

static class User{
private String name;
private int age;

public User(String name, int age) {
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;
}
}
}

五,原子更新数组

通过原子方式来更新数组的某个元素,

  • AtomicIntegerArray
  • AtomicLongArray
  • AtomicReferenceArray
public class AtomicIntegerArrayTest {

static int[] value = new int[]{1,2};

static AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(value);

public static void main(String[] args) {

System.out.println("--------->"+atomicIntegerArray.addAndGet(0,2));
System.out.println("--------->"+atomicIntegerArray.get(1));
System.out.println("--------->"+atomicIntegerArray.getAndSet(1,2));
}
}