一误墓、i++ 的原子性問題:int i=i++ 的操作實際上分為三個步驟“讀-改-寫”
第一步:int temp = i;
第二步:i = i + 1;
第三步:i = temp;
二、原子變量:在 java.util.concurrent.atomic 包下提供了一些原子變量尔邓。
- volatile 保證內(nèi)存可見性
- CAS(Compare-And-Swap) 算法保證數(shù)據(jù)變量的原子性付秕。CAS 算法是硬件對于并發(fā)操作的支持兰珍,CAS 包含了三個操作數(shù):
- 內(nèi)存值 V
- 預(yù)估值 A
- 更新值 B
當(dāng)且僅當(dāng) V == A 時, V = B; 否則询吴,不會執(zhí)行任何操作掠河。
A亮元、多線程操作,保證內(nèi)存變量原子性的示例代碼
import java.util.concurrent.atomic.AtomicInteger;
public class TestAtomicDemo {
public static void main(String[] args) {
// int i = 1;
// i = i++;
// System.out.println(i);
// 輸出1
AtomicDemo ad = new AtomicDemo();
for (int i = 0; i < 10; i++) {
new Thread(ad).start();
}
}
}
class AtomicDemo implements Runnable{
// 當(dāng)多線程操作時唠摹,volatile關(guān)鍵字無法保證原子性
// private volatile int serialNumber = 0;
private AtomicInteger serialNumber = new AtomicInteger(0);
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
System.out.println(getSerialNumber());
}
public int getSerialNumber(){
// return serialNumber++;
return serialNumber.getAndIncrement();
}
}
B爆捞、模擬 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();
boolean b = cas.compareAndSet(expectedValue, (int)(Math.random() * 101));
System.out.println(b);
}
}).start();
}
}
}
class CompareAndSwap{
private int value;
//獲取內(nèi)存值
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;
}
//設(shè)置
public synchronized boolean compareAndSet(int expectedValue, int newValue){
return expectedValue == compareAndSwap(expectedValue, newValue);
}
}