无锁数据结构,性能爆表!但要小心ABA问题和内存泄漏。
一、无锁栈(Treiber Stack)
实现
public class LockFreeStack<T> {
private static class Node<T> {
final T value;
Node<T> next;
Node(T value) {
this.value = value;
}
}
private final AtomicReference<Node<T>> top = new AtomicReference<>();
// 入栈
public void push(T value) {
Node<T> newNode = new Node<>(value);
Node<T> oldTop;
do {
oldTop = top.get();
newNode.next = oldTop;
} while (!top.compareAndSet(oldTop, newNode)); // CAS
}
// 出栈
public T pop() {
Node<T> oldTop;
Node<T> newTop;
do {
oldTop = top.get();
if (oldTop == null) {
return null;
}
newTop = oldTop.next;
} while (!top.compareAndSet(oldTop, newTop)); // CAS
return oldTop.value;
}
}
ABA问题解决
public class SafeLockFreeStack<T> {
private static class Node<T> {
final T value;
Node<T> next;
Node(T value) {
this.value = value;
}
}
// 使用版本号
private final AtomicStampedReference<Node<T>> top =
new AtomicStampedReference<>(null, 0);
public void push(T value) {
Node<T> newNode = new Node<>(value);
int[] stampHolder = new int[1];
Node<T> oldTop;
do {
oldTop = top.get(stampHolder);
int stamp = stampHolder[0];
newNode.next = oldTop;
} while (!top.compareAndSet(oldTop, newNode, stamp, stamp + 1));
}
public T pop() {
int[] stampHolder = new int[1];
Node<T> oldTop;
Node<T> newTop;
do {
oldTop = top.get(stampHolder);
if (oldTop == null) {
return null;
}
int stamp = stampHolder[0];
newTop = oldTop.next;
} while (!top.compareAndSet(oldTop, newTop, stamp, stamp + 1));
return oldTop.value;
}
}
二、无锁队列(Michael-Scott Queue)
实现
public class LockFreeQueue<T> {
private static class Node<T> {
final T value;
final AtomicReference<Node<T>> next = new AtomicReference<>();
Node(T value) {
this.value = value;
}
}
private final AtomicReference<Node<T>> head;
private final AtomicReference<Node<T>> tail;
public LockFreeQueue() {
Node<T> dummy = new Node<>(null);
head = new AtomicReference<>(dummy);
tail = new AtomicReference<>(dummy);
}
// 入队
public void enqueue(T value) {
Node<T> newNode = new Node<>(value);
while (true) {
Node<T> curTail = tail.get();
Node<T> tailNext = curTail.next.get();
if (curTail == tail.get()) {
if (tailNext != null) {
// 尾指针落后,先推进
tail.compareAndSet(curTail, tailNext);
} else {
// 尝试插入
if (curTail.next.compareAndSet(null, newNode)) {
// 成功,推进尾指针
tail.compareAndSet(curTail, newNode);
return;
}
}
}
}
}
// 出队
public T dequeue() {
while (true) {
Node<T> curHead = head.get();
Node<T> curTail = tail.get();
Node<T> headNext = curHead.next.get();
if (curHead == head.get()) {
if (curHead == curTail) {
if (headNext == null) {
return null; // 队列空
}
// 尾指针落后,推进
tail.compareAndSet(curTail, headNext);
} else {
T value = headNext.value;
if (head.compareAndSet(curHead, headNext)) {
return value;
}
}
}
}
}
}
三、性能对比
// 测试代码(略)
结果:
| 实现 | 吞吐量(ops/秒) | 竞争程度 |
|---|---|---|
| synchronized栈 | 500万 | 高 |
| 无锁栈 | 2000万 | 低 |
| BlockingQueue | 300万 | 高 |
| 无锁队列 | 1500万 | 低 |
四、注意事项⚠️
- ABA问题:用AtomicStampedReference
- 内存泄漏:及时清理节点
- 性能:竞争激烈时性能下降
- 复杂性:实现复杂,容易出错
下一篇→ Executor框架的设计哲学🏗️