一 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性能好;只能同步一个值。