MST

星途 面试题库

面试题:Java无锁编程中的CAS原理及应用

请详细解释Java无锁编程中CAS(Compare - and - Swap)的原理,以及在实际代码中如何基于CAS实现一个简单的无锁数据结构(如无锁队列的入队操作),并分析这种实现可能存在的问题。
16.5万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

CAS原理

CAS是一种无锁算法,用于在多线程环境下实现变量的原子性更新。其基本原理是:当一个线程尝试更新一个共享变量时,它会将当前值与预期值进行比较。如果当前值与预期值相等,说明在这个线程检查变量值之后没有其他线程修改过该变量,那么就将变量更新为新的值;如果当前值与预期值不相等,说明有其他线程在这个线程检查变量值之后修改了该变量,那么这个线程就需要重新读取当前值,再次尝试更新操作。

基于CAS实现无锁队列入队操作

以下是使用Java的AtomicReference来实现一个简单无锁队列的入队操作示例:

import java.util.concurrent.atomic.AtomicReference;

class Node<T> {
    T value;
    AtomicReference<Node<T>> next;

    Node(T value) {
        this.value = value;
        this.next = new AtomicReference<>(null);
    }
}

public class LockFreeQueue<T> {
    private AtomicReference<Node<T>> head;
    private AtomicReference<Node<T>> tail;

    public LockFreeQueue() {
        Node<T> dummy = new Node<>(null);
        head = new AtomicReference<>(dummy);
        tail = new AtomicReference<>(dummy);
    }

    public void enqueue(T item) {
        Node<T> newNode = new Node<>(item);
        while (true) {
            Node<T> curTail = tail.get();
            Node<T> next = curTail.next.get();
            if (curTail == tail.get()) {
                if (next == null) {
                    if (curTail.next.compareAndSet(null, newNode)) {
                        tail.compareAndSet(curTail, newNode);
                        return;
                    }
                } else {
                    tail.compareAndSet(curTail, next);
                }
            }
        }
    }
}

可能存在的问题

  1. ABA问题:当一个变量从A变为B,再变回A时,CAS操作可能会误认为该变量没有被修改过。可以通过引入版本号(如AtomicStampedReference)来解决。
  2. 循环开销:由于CAS操作可能会失败,需要不断重试,这会带来额外的CPU开销,尤其是在竞争激烈的情况下。
  3. 饥饿问题:某些线程可能因为不断重试CAS操作而得不到执行机会,导致饥饿。可以通过公平调度算法来缓解。