原创

Java面试题-CAS机制你知道多少?

CAS(Compare And Swap)是一种乐观锁的实现机制,用于多线程环境下的原子操作。在本教程中,我们将详细解释CAS的基本原理、使用场景以及实际应用示例,并通过更多的代码演示让初学者更好地理解这一机制。

1. CAS基本原理

CAS机制使用了三个基本操作数:内存地址V,旧的预期值A,要修改的新值B。其更新过程如下:

  1. 读取内存地址V的实际值。
  2. 比较实际值与预期值A是否相等。
  3. 如果相等,则将内存地址V的值修改为新值B,操作成功。
  4. 如果不相等,则重试整个过程,直到操作成功。

通过这个机制,CAS实现了在无锁的情况下进行原子操作,假设没有冲突,如果发生冲突,则通过重试机制保证操作的最终成功。

2. CAS应用示例

2.1 简单CAS示例

import java.util.concurrent.atomic.AtomicBoolean;

public class AtomicBooleanTest implements Runnable {
    private static AtomicBoolean flag = new AtomicBoolean(true);

    public static void main(String[] args) {
        AtomicBooleanTest ast = new AtomicBooleanTest();
        Thread thread1 = new Thread(ast);
        Thread thread2 = new Thread(ast);
        thread1.start();
        thread2.start();
    }

    @Override
    public void run() {
        System.out.println("Thread: " + Thread.currentThread().getName() + "; Flag: " + flag.get());
        if (flag.compareAndSet(true, false)) {
            System.out.println(Thread.currentThread().getName() + " " + flag.get());
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            flag.set(true);
        } else {
            System.out.println("Retry Thread: " + Thread.currentThread().getName() + "; Flag: " + flag.get());
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            run();
        }
    }
}

在这个示例中,两个线程通过CAS机制尝试将flag的值从true修改为false,并在成功后进行一定操作。通过不断的重试,实现了对共享资源的争抢和更新。

2.2 CAS的局限性

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerTest {
    private static AtomicInteger count = new AtomicInteger(0);

    public static void main(String[] args) {
        for (int i = 0; i < 2; i++) {
            new Thread(() -> {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 每个线程让count自增100次
                for (int j = 0; j < 100; j++) {
                    count.incrementAndGet();
                }
            }).start();
        }

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(count);
    }
}

在这个示例中,使用AtomicInteger保证了对count的原子操作,避免了线程安全问题。相比使用synchronized,性能更好。

3. 总结

CAS机制是一种乐观锁的实现,通过比较与替换来实现对共享资源的原子操作。在并发编程中,了解CAS的基本原理和应用场景对于保证线程安全性非常重要。然而,也需要注意CAS的局限性,选择合适的并发控制机制。

正文到此结束
本文目录