一 Atomic包
1、CAS Unsafe.compareAndSwapInt
2、AtomicLong LongAdder
3、AtomicReference 、AtomicReferenceFieldUpdater
package com.current.flame.test;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author haoxiansheng
*/
@Slf4j
public class AtomicExample1 {
private static AtomicReference<Integer> count = new AtomicReference<>(0);
@Getter
private volatile int sum = 100;
// 更新的必須由volatile關鍵字修飾 不能用static修飾(ExceptionInInitializerError)
private static AtomicIntegerFieldUpdater<AtomicExample1> updater = AtomicIntegerFieldUpdater.newUpdater(AtomicExample1.class, "sum");
private static AtomicExample1 atomicExample1 = new AtomicExample1();
public static void main(String[] args) {
count.compareAndSet(0, 2);
count.compareAndSet(0, 1);
count.compareAndSet(1, 3);
count.compareAndSet(2, 4);
count.compareAndSet(3, 5);
log.info("count=>{}", count.get());
if (updater.compareAndSet(atomicExample1, 100, 120)) {
log.info("update1 success=>{}", atomicExample1.getSum());
}
if (updater.compareAndSet(atomicExample1, 100, 120)) {
log.info("update2 success=>{}", atomicExample1.getSum());
} else {
log.info("update failed=>{}", atomicExample1.getSum());
}
}
}
4、AtomicStampReference: CAS 的ABA問題
package com.current.flame.test;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author haoxiansheng
*/
@Slf4j
public class AtomicExample2 {
private static AtomicBoolean isHappend = new AtomicBoolean(false);
// 請求總數
public static int clientTotal = 5000;
// 允許同時執行的線程併發數
public static int threadTotal = 200;
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal); // 信號量 允許有多少個同時執行
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal); // 閉鎖
for (int i = 0; i < clientTotal; i++) {
executorService.execute(()->{
try {
semaphore.acquire();
test();
semaphore.release();
} catch (Exception e) {
log.info("e=>{}", e.getMessage());
}
countDownLatch.countDown();
});
}
countDownLatch.await();
log.info("isHappend==>{}", isHappend.get());
executorService.shutdown();
}
private static void test() {
if (isHappend.compareAndSet(false, true)) {
log.info("execute");
}
}
}
二、原子性、鎖
1、synchroized: 依賴JVM
2、Lock: 依賴特殊的CPU 指令,代碼實現,ReentrantLock。
三、原子性、對比
1、synchroized:不可中斷、適合競爭不激烈,可讀性好
2、Lock: 可中斷鎖、多樣化同步、競爭激烈時能維持常態
3、Atomic:競爭激烈時能維持常態,比Lock性能好;只能同步一個值。