第6部分:无锁编程与原子操作
核心目标
理解高性能并发机制与CAS原理。
1. CAS(Compare-And-Swap)机制
CAS基本概念
CAS(Compare-And-Swap)是一种无锁的原子操作,它比较内存中的值与期望值,如果相等则更新为新值,否则不做任何操作。CAS操作是原子性的,由CPU指令保证。
CAS操作流程
public class CASExample {
private volatile int value = 0;
// CAS操作的伪代码
public boolean compareAndSwap(int expectedValue, int newValue) {
// 1. 读取内存中的当前值
int currentValue = value;
// 2. 比较当前值与期望值
if (currentValue == expectedValue) {
// 3. 如果相等,更新为新值
value = newValue;
return true; // 操作成功
} else {
// 4. 如果不相等,操作失败
return false; // 操作失败
}
}
// 实际的CAS操作(使用AtomicInteger)
private AtomicInteger atomicValue = new AtomicInteger(0);
public boolean atomicCompareAndSet(int expectedValue, int newValue) {
return atomicValue.compareAndSet(expectedValue, newValue);
}
}
CAS的实现原理
public class CASImplementation {
// CAS操作的底层实现(伪代码)
public synchronized boolean cas(int[] memory, int offset, int expected, int update) {
// 1. 读取内存地址offset处的值
int current = memory[offset];
// 2. 比较当前值与期望值
if (current == expected) {
// 3. 如果相等,原子性地更新为新值
memory[offset] = update;
return true;
} else {
// 4. 如果不相等,返回false
return false;
}
}
// 使用CPU的CAS指令(实际实现)
public native boolean compareAndSwapInt(Object obj, long offset, int expected, int update);
}
CAS的优势与劣势
public class CASAdvantagesAndDisadvantages {
private AtomicInteger counter = new AtomicInteger(0);
// 优势1:无锁,避免线程阻塞
public void advantage1() {
// 传统synchronized方式
synchronized (this) {
counter.incrementAndGet(); // 可能阻塞
}
// CAS方式
counter.incrementAndGet(); // 无阻塞,自旋重试
}
// 优势2:高性能,适合低竞争场景
public void advantage2() {
// 在低竞争情况下,CAS性能优于synchronized
for (int i = 0; i < 1000000; i++) {
counter.incrementAndGet();
}
}
// 劣势1:ABA问题
public void disadvantage1() {
// 线程1:读取值A
int value1 = counter.get();
// 线程2:A -> B -> A
counter.set(1);
counter.set(0);
// 线程1:CAS(A, C) 成功,但实际值已经被修改过
counter.compareAndSet(value1, 2);
}
// 劣势2:自旋消耗CPU
public void disadvantage2() {
// 在高竞争情况下,CAS会不断自旋重试
// 消耗大量CPU资源
while (!counter.compareAndSet(0, 1)) {
// 自旋等待
}
}
// 劣势3:只能保证一个变量的原子性
public void disadvantage3() {
// 无法保证多个变量的原子性操作
AtomicInteger a = new AtomicInteger(0);
AtomicInteger b = new AtomicInteger(0);
// 这两个操作不是原子的
a.incrementAndGet();
b.incrementAndGet();
}
}
2. AtomicInteger、AtomicReference等原子类
基本原子类
import java.util.concurrent.atomic.*;
public class BasicAtomicClasses {
// 1. AtomicInteger
private AtomicInteger atomicInt = new AtomicInteger(0);
public void atomicIntegerExample() {
// 基本操作
atomicInt.set(10); // 设置值
int value = atomicInt.get(); // 获取值
atomicInt.lazySet(20); // 延迟设置(不保证立即可见)
// 原子操作
int oldValue = atomicInt.getAndSet(30); // 获取并设置
int newValue = atomicInt.incrementAndGet(); // 自增并获取
int currentValue = atomicInt.getAndIncrement(); // 获取并自增
// CAS操作
boolean success = atomicInt.compareAndSet(30, 40);
boolean weakSuccess = atomicInt.weakCompareAndSet(40, 50);
// 原子更新
int result = atomicInt.updateAndGet(x -> x * 2);
int result2 = atomicInt.getAndUpdate(x -> x + 1);
}
// 2. AtomicLong
private AtomicLong atomicLong = new AtomicLong(0L);
public void atomicLongExample() {
atomicLong.set(100L);
long value = atomicLong.get();
atomicLong.incrementAndGet();
atomicLong.addAndGet(50L);
}
// 3. AtomicBoolean
private AtomicBoolean atomicBoolean = new AtomicBoolean(false);
public void atomicBooleanExample() {
atomicBoolean.set(true);
boolean value = atomicBoolean.get();
boolean oldValue = atomicBoolean.getAndSet(false);
boolean success = atomicBoolean.compareAndSet(false, true);
}
}
引用类型原子类
public class ReferenceAtomicClasses {
// 1. AtomicReference
private AtomicReference<String> atomicRef = new AtomicReference<>("initial");
public void atomicReferenceExample() {
// 基本操作
atomicRef.set("new value");
String value = atomicRef.get();
// CAS操作
boolean success = atomicRef.compareAndSet("new value", "updated value");
// 原子更新
String result = atomicRef.updateAndGet(s -> s.toUpperCase());
String result2 = atomicRef.getAndUpdate(s -> s + "!");
}
// 2. AtomicStampedReference(解决ABA问题)
private AtomicStampedReference<String> atomicStampedRef =
new AtomicStampedReference<>("initial", 0);
public void atomicStampedReferenceExample() {
String reference = atomicStampedRef.getReference();
int stamp = atomicStampedRef.getStamp();
// 带版本号的CAS操作
boolean success = atomicStampedRef.compareAndSet(
"initial", "new value", 0, 1);
// 获取引用和版本号
int[] stampHolder = new int[1];
String ref = atomicStampedRef.get(stampHolder);
int currentStamp = stampHolder[0];
}
// 3. AtomicMarkableReference
private AtomicMarkableReference<String> atomicMarkableRef =
new AtomicMarkableReference<>("initial", false);
public void atomicMarkableReferenceExample() {
boolean[] markHolder = new boolean[1];
String ref = atomicMarkableRef.get(markHolder);
boolean marked = markHolder[0];
// 带标记的CAS操作
boolean success = atomicMarkableRef.compareAndSet(
"initial", "new value", false, true);
}
}
数组原子类
public class ArrayAtomicClasses {
// 1. AtomicIntegerArray
private AtomicIntegerArray atomicIntArray = new AtomicIntegerArray(10);
public void atomicIntegerArrayExample() {
// 基本操作
atomicIntArray.set(0, 100);
int value = atomicIntArray.get(0);
// 原子操作
int oldValue = atomicIntArray.getAndSet(0, 200);
int newValue = atomicIntArray.incrementAndGet(0);
// CAS操作
boolean success = atomicIntArray.compareAndSet(0, 200, 300);
// 原子更新
int result = atomicIntArray.updateAndGet(0, x -> x * 2);
}
// 2. AtomicLongArray
private AtomicLongArray atomicLongArray = new AtomicLongArray(5);
public void atomicLongArrayExample() {
atomicLongArray.set(0, 1000L);
long value = atomicLongArray.get(0);
atomicLongArray.addAndGet(0, 500L);
}
// 3. AtomicReferenceArray
private AtomicReferenceArray<String> atomicRefArray =
new AtomicReferenceArray<>(10);
public void atomicReferenceArrayExample() {
atomicRefArray.set(0, "hello");
String value = atomicRefArray.get(0);
boolean success = atomicRefArray.compareAndSet(0, "hello", "world");
}
}
字段更新器
public class FieldUpdaterClasses {
private volatile int field = 0;
private volatile String stringField = "initial";
// 1. AtomicIntegerFieldUpdater
private static final AtomicIntegerFieldUpdater<FieldUpdaterClasses> fieldUpdater =
AtomicIntegerFieldUpdater.newUpdater(FieldUpdaterClasses.class, "field");
public void atomicIntegerFieldUpdaterExample() {
// 更新volatile字段
fieldUpdater.set(this, 100);
int value = fieldUpdater.get(this);
// 原子操作
int oldValue = fieldUpdater.getAndSet(this, 200);
int newValue = fieldUpdater.incrementAndGet(this);
// CAS操作
boolean success = fieldUpdater.compareAndSet(this, 200, 300);
}
// 2. AtomicReferenceFieldUpdater
private static final AtomicReferenceFieldUpdater<FieldUpdaterClasses, String> refFieldUpdater =
AtomicReferenceFieldUpdater.newUpdater(FieldUpdaterClasses.class, String.class, "stringField");
public void atomicReferenceFieldUpdaterExample() {
refFieldUpdater.set(this, "new value");
String value = refFieldUpdater.get(this);
boolean success = refFieldUpdater.compareAndSet(this, "new value", "updated value");
}
}
3. ABA问题与AtomicStampedReference
ABA问题详解
public class ABAProblem {
private AtomicReference<String> atomicRef = new AtomicReference<>("A");
public void demonstrateABAProblem() throws InterruptedException {
// 线程1:读取值A
Thread thread1 = new Thread(() -> {
String value = atomicRef.get();
System.out.println("线程1读取到: " + value);
try {
Thread.sleep(1000); // 模拟处理时间
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 尝试将A改为C
boolean success = atomicRef.compareAndSet(value, "C");
System.out.println("线程1 CAS结果: " + success);
});
// 线程2:A -> B -> A
Thread thread2 = new Thread(() -> {
try {
Thread.sleep(500); // 等待线程1读取值
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// A -> B
atomicRef.compareAndSet("A", "B");
System.out.println("线程2: A -> B");
// B -> A
atomicRef.compareAndSet("B", "A");
System.out.println("线程2: B -> A");
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("最终值: " + atomicRef.get());
}
}
使用AtomicStampedReference解决ABA问题
public class ABAProblemSolution {
private AtomicStampedReference<String> atomicStampedRef =
new AtomicStampedReference<>("A", 0);
public void solveABAProblem() throws InterruptedException {
// 线程1:读取值A和版本号
Thread thread1 = new Thread(() -> {
int[] stampHolder = new int[1];
String value = atomicStampedRef.get(stampHolder);
int stamp = stampHolder[0];
System.out.println("线程1读取到: " + value + ", 版本: " + stamp);
try {
Thread.sleep(1000); // 模拟处理时间
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 尝试将A改为C,版本号必须匹配
boolean success = atomicStampedRef.compareAndSet(value, "C", stamp, stamp + 1);
System.out.println("线程1 CAS结果: " + success);
});
// 线程2:A -> B -> A,版本号会改变
Thread thread2 = new Thread(() -> {
try {
Thread.sleep(500); // 等待线程1读取值
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// A -> B,版本号从0变为1
atomicStampedRef.compareAndSet("A", "B", 0, 1);
System.out.println("线程2: A -> B, 版本: 0 -> 1");
// B -> A,版本号从1变为2
atomicStampedRef.compareAndSet("B", "A", 1, 2);
System.out.println("线程2: B -> A, 版本: 1 -> 2");
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
int[] stampHolder = new int[1];
String finalValue = atomicStampedRef.get(stampHolder);
int finalStamp = stampHolder[0];
System.out.println("最终值: " + finalValue + ", 版本: " + finalStamp);
}
}
版本号机制
public class VersionMechanism {
private AtomicStampedReference<Integer> versionedRef =
new AtomicStampedReference<>(0, 0);
public void versionMechanismExample() {
// 模拟多次修改
for (int i = 0; i < 5; i++) {
int[] stampHolder = new int[1];
Integer currentValue = versionedRef.get(stampHolder);
int currentStamp = stampHolder[0];
// 更新值和版本号
boolean success = versionedRef.compareAndSet(
currentValue,
currentValue + 1,
currentStamp,
currentStamp + 1
);
System.out.println("更新 " + i + ": " + success +
", 值: " + versionedRef.getReference() +
", 版本: " + versionedRef.getStamp());
}
}
// 检查值是否被修改过
public boolean hasValueChanged(int expectedValue, int expectedStamp) {
int[] stampHolder = new int[1];
Integer currentValue = versionedRef.get(stampHolder);
int currentStamp = stampHolder[0];
return currentValue != expectedValue || currentStamp != expectedStamp;
}
}
4. LongAdder、DoubleAdder原理
LongAdder原理
import java.util.concurrent.atomic.LongAdder;
public class LongAdderExample {
private LongAdder longAdder = new LongAdder();
public void longAdderBasicUsage() {
// 基本操作
longAdder.add(10); // 增加10
longAdder.increment(); // 增加1
longAdder.decrement(); // 减少1
longAdder.add(-5); // 减少5
// 获取值
long sum = longAdder.sum(); // 获取当前总和
longAdder.reset(); // 重置为0
long sumAfterReset = longAdder.sum();
System.out.println("总和: " + sum);
System.out.println("重置后: " + sumAfterReset);
}
// LongAdder vs AtomicLong性能对比
public void performanceComparison() throws InterruptedException {
int threadCount = 10;
int operationsPerThread = 100000;
// 测试AtomicLong
AtomicLong atomicLong = new AtomicLong(0);
long start = System.currentTimeMillis();
Thread[] atomicThreads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
atomicThreads[i] = new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
atomicLong.incrementAndGet();
}
});
atomicThreads[i].start();
}
for (Thread thread : atomicThreads) {
thread.join();
}
long atomicTime = System.currentTimeMillis() - start;
System.out.println("AtomicLong时间: " + atomicTime + "ms, 结果: " + atomicLong.get());
// 测试LongAdder
LongAdder longAdder = new LongAdder();
start = System.currentTimeMillis();
Thread[] adderThreads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
adderThreads[i] = new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
longAdder.increment();
}
});
adderThreads[i].start();
}
for (Thread thread : adderThreads) {
thread.join();
}
long adderTime = System.currentTimeMillis() - start;
System.out.println("LongAdder时间: " + adderTime + "ms, 结果: " + longAdder.sum());
}
}
LongAdder内部原理
public class LongAdderInternalPrinciple {
// LongAdder内部结构(简化版)
private static class LongAdderInternal {
private volatile long base; // 基础值
private volatile Cell[] cells; // 分段计数器数组
private volatile int cellsBusy; // 数组扩容标志
// 内部Cell类
private static class Cell {
volatile long value;
Cell(long x) { value = x; }
}
// 增加操作
public void add(long x) {
Cell[] as = cells;
if (as == null) {
// 如果cells为null,尝试更新base
if (casBase(base, base + x)) {
return;
}
// 如果更新base失败,初始化cells
if (cells == null) {
initCells();
}
}
// 使用cells进行分段计数
int index = getProbe() & (as.length - 1);
Cell cell = as[index];
if (cell == null) {
if (cellsBusy == 0) {
Cell newCell = new Cell(x);
if (cellsBusy == 0 && casCellsBusy()) {
try {
if (cells[index] == null) {
cells[index] = newCell;
return;
}
} finally {
cellsBusy = 0;
}
}
}
add(x); // 重试
} else {
if (cell.cas(cell.value, cell.value + x)) {
return;
}
add(x); // 重试
}
}
// 获取总和
public long sum() {
long sum = base;
Cell[] as = cells;
if (as != null) {
for (Cell cell : as) {
if (cell != null) {
sum += cell.value;
}
}
}
return sum;
}
// CAS操作(伪代码)
private boolean casBase(long expected, long update) {
// 使用CAS更新base值
return true; // 简化实现
}
private boolean casCellsBusy() {
// 使用CAS设置cellsBusy标志
return true; // 简化实现
}
private void initCells() {
// 初始化cells数组
}
private int getProbe() {
// 获取线程的探针值
return Thread.currentThread().hashCode();
}
}
}
DoubleAdder使用
import java.util.concurrent.atomic.DoubleAdder;
public class DoubleAdderExample {
private DoubleAdder doubleAdder = new DoubleAdder();
public void doubleAdderUsage() {
// 基本操作
doubleAdder.add(10.5); // 增加10.5
doubleAdder.add(-3.2); // 减少3.2
// 获取值
double sum = doubleAdder.sum();
doubleAdder.reset();
System.out.println("总和: " + sum);
}
// 性能测试
public void performanceTest() throws InterruptedException {
int threadCount = 10;
int operationsPerThread = 100000;
DoubleAdder doubleAdder = new DoubleAdder();
long start = System.currentTimeMillis();
Thread[] threads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
doubleAdder.add(1.0);
}
});
threads[i].start();
}
for (Thread thread : threads) {
thread.join();
}
long time = System.currentTimeMillis() - start;
System.out.println("DoubleAdder时间: " + time + "ms, 结果: " + doubleAdder.sum());
}
}
5. 无锁队列(ConcurrentLinkedQueue)
ConcurrentLinkedQueue基本用法
import java.util.concurrent.ConcurrentLinkedQueue;
public class ConcurrentLinkedQueueExample {
private ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
public void basicUsage() {
// 添加元素
queue.offer("item1");
queue.offer("item2");
queue.offer("item3");
// 获取并移除元素
String item = queue.poll();
System.out.println("取出: " + item);
// 获取但不移除元素
String peekItem = queue.peek();
System.out.println("查看: " + peekItem);
// 检查是否为空
boolean isEmpty = queue.isEmpty();
System.out.println("是否为空: " + isEmpty);
// 获取大小(注意:这个操作是O(n)的)
int size = queue.size();
System.out.println("大小: " + size);
}
// 生产者-消费者模式
public void producerConsumerExample() throws InterruptedException {
ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<>();
// 生产者
Thread producer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
queue.offer(i);
System.out.println("生产: " + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
// 消费者
Thread consumer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
Integer item = queue.poll();
if (item != null) {
System.out.println("消费: " + item);
}
try {
Thread.sleep(150);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
producer.start();
consumer.start();
producer.join();
consumer.join();
}
}
无锁队列的实现原理
public class LockFreeQueueImplementation {
// 无锁队列的节点
private static class Node<T> {
volatile T item;
volatile Node<T> next;
Node(T item) {
this.item = item;
}
}
// 无锁队列实现(简化版)
private static class LockFreeQueue<T> {
private volatile Node<T> head;
private volatile Node<T> tail;
public LockFreeQueue() {
Node<T> dummy = new Node<>(null);
head = dummy;
tail = dummy;
}
// 入队操作
public boolean offer(T item) {
Node<T> newNode = new Node<>(item);
while (true) {
Node<T> last = tail;
Node<T> next = last.next;
if (last == tail) {
if (next == null) {
// 尝试将新节点链接到最后一个节点
if (casNext(last, next, newNode)) {
// 更新tail指针
casTail(tail, newNode);
return true;
}
} else {
// 帮助其他线程推进tail指针
casTail(tail, next);
}
}
}
}
// 出队操作
public T poll() {
while (true) {
Node<T> first = head;
Node<T> last = tail;
Node<T> next = first.next;
if (first == head) {
if (first == last) {
if (next == null) {
return null; // 队列为空
}
// 帮助推进tail指针
casTail(last, next);
} else {
T item = next.item;
if (item != null) {
next.item = null;
casHead(first, next);
return item;
}
}
}
}
}
// CAS操作(伪代码)
private boolean casNext(Node<T> node, Node<T> expected, Node<T> update) {
// 使用CAS更新next指针
return true; // 简化实现
}
private boolean casTail(Node<T> expected, Node<T> update) {
// 使用CAS更新tail指针
return true; // 简化实现
}
private boolean casHead(Node<T> expected, Node<T> update) {
// 使用CAS更新head指针
return true; // 简化实现
}
}
}
性能对比
public class QueuePerformanceComparison {
public void performanceTest() throws InterruptedException {
int threadCount = 10;
int operationsPerThread = 100000;
// 测试ConcurrentLinkedQueue
ConcurrentLinkedQueue<Integer> concurrentQueue = new ConcurrentLinkedQueue<>();
long start = System.currentTimeMillis();
Thread[] concurrentThreads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
concurrentThreads[i] = new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
concurrentQueue.offer(j);
concurrentQueue.poll();
}
});
concurrentThreads[i].start();
}
for (Thread thread : concurrentThreads) {
thread.join();
}
long concurrentTime = System.currentTimeMillis() - start;
System.out.println("ConcurrentLinkedQueue时间: " + concurrentTime + "ms");
// 测试synchronized队列
Queue<Integer> synchronizedQueue = new LinkedList<>();
Object lock = new Object();
start = System.currentTimeMillis();
Thread[] syncThreads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
syncThreads[i] = new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
synchronized (lock) {
synchronizedQueue.offer(j);
synchronizedQueue.poll();
}
}
});
syncThreads[i].start();
}
for (Thread thread : syncThreads) {
thread.join();
}
long syncTime = System.currentTimeMillis() - start;
System.out.println("Synchronized队列时间: " + syncTime + "ms");
}
}
6. StampedLock与读写锁优化
StampedLock基本用法
import java.util.concurrent.locks.StampedLock;
public class StampedLockExample {
private final StampedLock stampedLock = new StampedLock();
private int value = 0;
// 写操作
public void write(int newValue) {
long stamp = stampedLock.writeLock();
try {
value = newValue;
System.out.println("写入: " + newValue);
} finally {
stampedLock.unlockWrite(stamp);
}
}
// 读操作(悲观读)
public int read() {
long stamp = stampedLock.readLock();
try {
System.out.println("读取: " + value);
return value;
} finally {
stampedLock.unlockRead(stamp);
}
}
// 乐观读
public int optimisticRead() {
long stamp = stampedLock.tryOptimisticRead();
int currentValue = value;
if (!stampedLock.validate(stamp)) {
// 乐观读失败,升级为悲观读
stamp = stampedLock.readLock();
try {
currentValue = value;
} finally {
stampedLock.unlockRead(stamp);
}
}
System.out.println("乐观读取: " + currentValue);
return currentValue;
}
// 读锁升级为写锁
public void readToWriteUpgrade() {
long stamp = stampedLock.readLock();
try {
while (value == 0) {
long writeStamp = stampedLock.tryConvertToWriteLock(stamp);
if (writeStamp != 0) {
stamp = writeStamp;
value = 42;
break;
} else {
stampedLock.unlockRead(stamp);
stamp = stampedLock.writeLock();
}
}
} finally {
stampedLock.unlock(stamp);
}
}
}
StampedLock vs ReentrantReadWriteLock
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class StampedLockVsReadWriteLock {
private final StampedLock stampedLock = new StampedLock();
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private int value = 0;
// StampedLock实现
public void stampedLockWrite(int newValue) {
long stamp = stampedLock.writeLock();
try {
value = newValue;
} finally {
stampedLock.unlockWrite(stamp);
}
}
public int stampedLockRead() {
long stamp = stampedLock.readLock();
try {
return value;
} finally {
stampedLock.unlockRead(stamp);
}
}
// ReentrantReadWriteLock实现
public void readWriteLockWrite(int newValue) {
readWriteLock.writeLock().lock();
try {
value = newValue;
} finally {
readWriteLock.writeLock().unlock();
}
}
public int readWriteLockRead() {
readWriteLock.readLock().lock();
try {
return value;
} finally {
readWriteLock.readLock().unlock();
}
}
// 性能对比
public void performanceComparison() throws InterruptedException {
int threadCount = 10;
int operationsPerThread = 100000;
// 测试StampedLock
long start = System.currentTimeMillis();
Thread[] stampedThreads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
stampedThreads[i] = new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
if (j % 10 == 0) {
stampedLockWrite(j);
} else {
stampedLockRead();
}
}
});
stampedThreads[i].start();
}
for (Thread thread : stampedThreads) {
thread.join();
}
long stampedTime = System.currentTimeMillis() - start;
System.out.println("StampedLock时间: " + stampedTime + "ms");
// 测试ReentrantReadWriteLock
start = System.currentTimeMillis();
Thread[] readWriteThreads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
readWriteThreads[i] = new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
if (j % 10 == 0) {
readWriteLockWrite(j);
} else {
readWriteLockRead();
}
}
});
readWriteThreads[i].start();
}
for (Thread thread : readWriteThreads) {
thread.join();
}
long readWriteTime = System.currentTimeMillis() - start;
System.out.println("ReentrantReadWriteLock时间: " + readWriteTime + "ms");
}
}
乐观读的使用场景
public class OptimisticReadExample {
private final StampedLock stampedLock = new StampedLock();
private int value = 0;
private long lastModified = 0;
// 写操作
public void write(int newValue) {
long stamp = stampedLock.writeLock();
try {
value = newValue;
lastModified = System.currentTimeMillis();
} finally {
stampedLock.unlockWrite(stamp);
}
}
// 乐观读操作
public int optimisticRead() {
long stamp = stampedLock.tryOptimisticRead();
int currentValue = value;
long currentLastModified = lastModified;
// 验证读操作期间是否有写操作
if (!stampedLock.validate(stamp)) {
// 乐观读失败,升级为悲观读
stamp = stampedLock.readLock();
try {
currentValue = value;
currentLastModified = lastModified;
} finally {
stampedLock.unlockRead(stamp);
}
}
return currentValue;
}
// 条件性读操作
public int conditionalRead(int expectedValue) {
long stamp = stampedLock.tryOptimisticRead();
int currentValue = value;
if (currentValue == expectedValue && stampedLock.validate(stamp)) {
return currentValue;
}
// 乐观读失败或条件不满足,使用悲观读
stamp = stampedLock.readLock();
try {
currentValue = value;
return currentValue;
} finally {
stampedLock.unlockRead(stamp);
}
}
}
实践练习
练习1:无锁计数器实现
public class LockFreeCounter {
private final AtomicInteger counter = new AtomicInteger(0);
public void increment() {
counter.incrementAndGet();
}
public void decrement() {
counter.decrementAndGet();
}
public int get() {
return counter.get();
}
public void add(int delta) {
counter.addAndGet(delta);
}
// 测试方法
public static void main(String[] args) throws InterruptedException {
LockFreeCounter counter = new LockFreeCounter();
int threadCount = 10;
int operationsPerThread = 100000;
Thread[] threads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
counter.increment();
}
});
threads[i].start();
}
for (Thread thread : threads) {
thread.join();
}
System.out.println("期望结果: " + (threadCount * operationsPerThread));
System.out.println("实际结果: " + counter.get());
}
}
练习2:无锁栈实现
public class LockFreeStack<T> {
private static class Node<T> {
final T item;
volatile Node<T> next;
Node(T item) {
this.item = item;
}
}
private volatile Node<T> head;
public void push(T item) {
Node<T> newNode = new Node<>(item);
Node<T> currentHead;
do {
currentHead = head;
newNode.next = currentHead;
} while (!casHead(currentHead, newNode));
}
public T pop() {
Node<T> currentHead;
Node<T> newHead;
do {
currentHead = head;
if (currentHead == null) {
return null;
}
newHead = currentHead.next;
} while (!casHead(currentHead, newHead));
return currentHead.item;
}
public boolean isEmpty() {
return head == null;
}
// CAS操作(伪代码)
private boolean casHead(Node<T> expected, Node<T> update) {
// 使用AtomicReferenceFieldUpdater或Unsafe实现
return true; // 简化实现
}
}
总结
本部分深入介绍了无锁编程与原子操作的核心概念:
- CAS机制:理解无锁编程的基础
- 原子类:掌握各种原子类的使用方法
- ABA问题:了解并解决ABA问题
- LongAdder:学习分段计数器的原理
- 无锁队列:理解无锁数据结构的实现
- StampedLock:掌握读写锁的优化
这些技术是构建高性能并发系统的重要工具,下一部分将学习Fork/Join框架与并行流。
1322

被折叠的 条评论
为什么被折叠?



