在并发编程中,“无锁方案”是指不使用传统的互斥锁(如 synchronized、ReentrantLock)来实现线程安全,而是依赖 CAS(Compare-And-Swap)、原子变量、volatile、内存屏障等机制,达到无阻塞(Non-blocking)或最小阻塞的高性能并发效果。
一、无锁方案的设计思想
- 基于 CAS 操作的原子更新:
-
CAS 保证变量更新是原子的,核心是:
1
如果当前值 == 预期值,则更新为新值;否则失败重试。
1
2. **避免临界区竞争**:
-
不进入阻塞的临界区,而是通过重试等方式避免锁。
- 无锁结构通常需要自旋(Spin)机制。
- 适用于冲突较少或可接受短暂失败重试的场景。
二、无锁方案常见场景
| 场景/结构 | Java 方案 |
|---|---|
| 原子变量 | AtomicInteger, AtomicReference 等 |
| 无锁队列 | ConcurrentLinkedQueue |
| 无锁栈 | 自定义或 ConcurrentLinkedDeque |
| 原子字段更新 | AtomicIntegerFieldUpdater |
| LongAdder | 低冲突计数器,无锁设计 |
三、Java 无锁代码示例
1. 基于 AtomicInteger 实现的无锁计数器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.util.concurrent.atomic.AtomicInteger;
public class LockFreeCounter {
private final AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet(); // CAS 保证原子性
}
public int get() {
return count.get();
}
public static void main(String[] args) throws InterruptedException {
LockFreeCounter counter = new LockFreeCounter();
Runnable task = () -> {
for (int i = 0; i < 10000; i++) {
counter.increment();
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Final count: " + counter.get()); // 应该是 20000
}
}
2. 无锁栈(基于 AtomicReference 实现)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.util.concurrent.atomic.AtomicReference;
public class LockFreeStack<T> {
private static class Node<T> {
final T value;
final Node<T> next;
Node(T value, Node<T> next) {
this.value = value;
this.next = next;
}
}
private final AtomicReference<Node<T>> head = new AtomicReference<>();
public void push(T value) {
Node<T> newHead;
Node<T> oldHead;
do {
oldHead = head.get();
newHead = new Node<>(value, oldHead);
} while (!head.compareAndSet(oldHead, newHead));
}
public T pop() {
Node<T> oldHead;
Node<T> newHead;
do {
oldHead = head.get();
if (oldHead == null) return null;
newHead = oldHead.next;
} while (!head.compareAndSet(oldHead, newHead));
return oldHead.value;
}
public static void main(String[] args) {
LockFreeStack<Integer> stack = new LockFreeStack<>();
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println(stack.pop()); // 3
System.out.println(stack.pop()); // 2
System.out.println(stack.pop()); // 1
}
}
3. 无锁队列:Java 提供的 ConcurrentLinkedQueue
1
2
3
4
5
6
7
8
9
10
11
12
13
import java.util.concurrent.ConcurrentLinkedQueue;
public class LockFreeQueueExample {
public static void main(String[] args) {
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
queue.offer("a");
queue.offer("b");
System.out.println(queue.poll()); // a
System.out.println(queue.poll()); // b
}
}
4. LongAdder 示例:高并发无锁累加器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.concurrent.atomic.LongAdder;
public class LongAdderExample {
public static void main(String[] args) throws InterruptedException {
LongAdder adder = new LongAdder();
Runnable task = () -> {
for (int i = 0; i < 10000; i++) {
adder.increment();
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Total: " + adder.sum()); // 应为 20000
}
}
四、无锁方案优缺点
✅ 优点:
- 高性能(适合高并发读写)
- 无线程阻塞和上下文切换开销
- 不容易死锁
缺点:
- 代码复杂,调试困难
- ABA 问题(CAS 中经典问题)
- 适合简单逻辑,不适合复杂状态管理
五、总结
| 类别 | Java 无锁类 | 是否底层使用 CAS |
|---|---|---|
| 计数器 | AtomicInteger、LongAdder |
✅ |
| 队列 | ConcurrentLinkedQueue |
✅ |
| 栈 | 自定义/无锁链栈 | ✅ |
| 引用管理 | AtomicReference |
✅ |
