文章目錄
-
- 原子變量
- CAS算法
- 執行個體dome
- 模拟CAS算法
原子變量
- 類的小工具包,支援在單個變量上解除鎖的線程安全程式設計。事實上,此包中的類可将 volatile值、字段和數組元素的概念擴充到那些也提供原子條件更新操作的類。
- 類 AtomicBoolean、 AtomicInteger、 AtomicLong和 AtomicReference的執行個體各自提供對相應類型單個變量的通路和更新。每個類也為該類型提供适當的實用工具方法。
- AtomicIntegerArray、 AtomicLongArray和 AtomicReferencearray類進一步擴充了原子操作,對這些類型的數組提供了支援。這些類在為其數組元素提供 volatile通路語義方面也引人注目,這對于普通數組來說是不受支援的。
- 核心方法:boolean compareAndSet(expectedValue,updateValue);
- java.util.concurrent.atomic包下提供了一些原子操作的常用類:
- AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference
- AtomicIntegerArray、AtomicLongArray
- AtomicMarkableReference
- AtomicReferenceArray
- AtomicStampedReference
CAS算法
- CAS( Compare-And-Swap)是一種硬體對并發的支援,針對多處理器操作而設計的處理器中的一種特殊指令,用于管理對共享資料的并發通路。
- CAS是一種無鎖的非阻塞算法的實作。
- CAS包含了3個操作數
- 需要讀寫的記憶體值V
- 進行比較的值A
- 拟寫入的新值B
- 當且僅當v的值等于A時,CAS通過原子方式用新值B來更新V的值,否則不會執行任何操作。
執行個體dome
注釋部分為原來的代碼。
/*
* 一、 i++ 的原子性問題:i++ 的操作實際上分為三個步驟“讀-改-寫”
*
* int i = 10;
* i = i++;//10
*
* int temp = i;
* i = i + 1;
* i = temp;
* 二、 原子變量:jdk1.5 後java.util.concurrent.atomic 包下提供了常用的的原子變量
* 1. 裡面封裝的value 都用 volatile修飾 保證記憶體可見性
* 2. CAS(Compare-And-Swap) 算法保證資料的原子性
* CAS 算法是硬體對于并發操作共享資料的支援
* CAS 包含了三個操作數:
* 記憶體值 V
* 預估值 A
* 更新值 B
* 當且僅當 V == A 時,才會把 B的值賦給A,否則,不做任何操作。
*/
public class TestAtomicDemo {
public static void main(String[] args) {
AtomicDemo ad = new AtomicDemo();
for (int i = 0; i < 10; i++) {
new Thread(ad).start();
}
}
}
class AtomicDemo implements Runnable{
// private volatile int serialNumber = 0;
private AtomicInteger serialNumber = new AtomicInteger();
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " : " + getSerialNumber());
}
public int getSerialNumber() {
// return serialNumber++;
return serialNumber.getAndIncrement();
}
}
模拟CAS算法
這段代碼有點難了解,看不懂可以留言。
/*
* 模拟cas算法
*/
public class TestCompareAndSwap {
public static void main(String[] args) {
final CompareAndSwap cas = new CompareAndSwap();
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
int expectedValue = cas.get();
int i = (int)(Math.random()*101);
System.out.println(expectedValue+ " " +i);
boolean b = cas.compareAndSet(expectedValue, i);
System.out.println(b);
}
}).start();;
}
}
}
class CompareAndSwap{
private int value;
//擷取記憶體值
public synchronized int get() {
return value;
}
//比較
public synchronized int compareAndSwap(int expectedValue, int newValue) {
int oldValue = value;
if(oldValue == expectedValue) {
this.value = newValue;
}
return oldValue;
}
//設定
public synchronized boolean compareAndSet(int expectedValue,int newValue) {
return expectedValue == compareAndSwap(expectedValue, newValue);
}
}