Home 并发编程:无锁方案 CAS
Post
Cancel

并发编程:无锁方案 CAS

在并发编程中,“无锁方案”是指不使用传统的互斥锁(如 synchronizedReentrantLock)来实现线程安全,而是依赖 CAS(Compare-And-Swap)原子变量volatile内存屏障等机制,达到无阻塞(Non-blocking)或最小阻塞的高性能并发效果。


一、无锁方案的设计思想

  1. 基于 CAS 操作的原子更新
  • CAS 保证变量更新是原子的,核心是:

    1
    
    如果当前值 == 预期值,则更新为新值;否则失败重试。
    
    1
    
        2. **避免临界区竞争**:
    
  • 不进入阻塞的临界区,而是通过重试等方式避免锁。

    1. 无锁结构通常需要自旋(Spin)机制
    2. 适用于冲突较少或可接受短暂失败重试的场景

二、无锁方案常见场景

场景/结构 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
计数器 AtomicIntegerLongAdder
队列 ConcurrentLinkedQueue
自定义/无锁链栈
引用管理 AtomicReference

weixin.png

公众号名称:怪味Coding
微信扫码关注或搜索公众号名称
This post is licensed under CC BY 4.0 by the author.

并发编程:起源

Reactor 和 Proactor 这两个高性能网络模式