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最終結果一定是1000for (int i=0;i<100;i++){list.add(new Thread(new Runnable() {@Overridepublic 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( //8msaRperson.get(), //如果滿足我的預期,就進行修改;不滿足就不修改new Person("Tom", aRperson.get().getAge() + 2)));System.out.println("Thread2 Atomic References "+ aRperson.get().toString());}}
}
?