Atomic系列类别
Atomic系列类封装了一系列的基础类型和对象操作,其主要目的就是为了实现原子性,主要核心类如下
- AtomicInteger
- AtomicLong
- AtomicBoolean
- AtomicIntegerArray
- AtomicLongArray
- AtomicReference 原子性的引用对象
- 在对Atomic类操作的时候,如果是有多个操作执行,那么就是非原子性的,需要加synchronized进行修饰,保证Atomic类操作整体原子性
package com.example.core.cas;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class UseAtomic {
private static /* int count = 0*/AtomicInteger count = new AtomicInteger(0);
public synchronized int add(){//使用synchronized关键字使得多个操作合并在一起,形成一个整体
//return count.addAndGet(10);将+1+2+3+4代替+10,模拟多个操作
count.addAndGet(1);
count.addAndGet(2);
count.addAndGet(3);
count.addAndGet(4);
return count.get();
}
public static void main(String[] args) {
UseAtomic ua = new UseAtomic();
List<Thread> list = new ArrayList<>();
//如果使用atomicInteger最终结果一定是1000
for (int i=0;i<100;i++){
list.add(new Thread(new Runnable() {
@Override
public void run() {
System.out.println("累计结果:"+ua.add());
}
}));
}
for(Thread t:list){
t.start();
}
}
}
另一个例子
- Person.class
package com.example.core.cas;
public class Person {
private String name;
private int age;
public Person(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;
}
public String toString() {
return "[name: " + this.name + ", age: " + this.age + "]";
}
}
- 多个线程抢占同一份资源,会造成问题
package com.example.core.cas;
public class UseAtomicReference1 {
private static Person person;
public static void main(String[] args) throws InterruptedException {
person = new Person("Tom", 18);
System.out.println("Person is " + person.toString());
Thread t1 = new Thread(new Task1());
Thread t2 = new Thread(new Task2());
t1.start();
t2.start();
t1.join();
t2.join();
Thread.sleep(100);
System.out.println("Now Person is " + person.toString());
}
static class Task1 implements Runnable {
public void run() {
person.setAge(19);
person.setName("Tom1");
System.out.println("Thread1 Values "
+ person.toString());
}
}
static class Task2 implements Runnable {
public void run() {
person.setAge(20);
person.setName("Tom2");
System.out.println("Thread2 Values "
+ person.toString());
}
}
}
- 使用Atomic,如果两个线程逐次访问并修改资源,可以保证数据一致性;如果同时访问,其中一个就会返回false,不修改数据
- 避免产生并发行
package com.example.core.cas;
import java.util.concurrent.atomic.AtomicReference;
public class UseAtomicReference2 {
// 普通引用
private static Person person;
// 原子性引用
private static AtomicReference<Person> aRperson;
public static void main(String[] args) throws InterruptedException {
person = new Person("Tom", 18);
aRperson = new AtomicReference<Person>(person);
System.out.println("Atomic Person is " + aRperson.get().toString());
Thread t1 = new Thread(new Task1());
Thread t2 = new Thread(new Task2());
t1.start();
t2.start();
t1.join();
t2.join();
Thread.sleep(500);
System.out.println("Now Atomic Person is " + aRperson.get().toString());
}
static class Task1 implements Runnable {
public void run() {
System.err.println("ret = " +
// C A S 原子操作
aRperson.compareAndSet( //10ms
aRperson.get(), //如果满足我的预期,就进行修改;不满足就不修改
new Person("Tom", aRperson.get().getAge() + 1)
));
System.out.println("Thread1 Atomic References "
+ aRperson.get().toString());
}
}
static class Task2 implements Runnable {
public void run() {
System.err.println("ret = " +
aRperson.compareAndSet( //8ms
aRperson.get(), //如果满足我的预期,就进行修改;不满足就不修改
new Person("Tom", aRperson.get().getAge() + 2)
));
System.out.println("Thread2 Atomic References "
+ aRperson.get().toString());
}
}
}