什么是 CAS?Java 中如何使用 CAS

旧城等待, 2023-10-14 04:25 129阅读 0赞

CAS是Compare And Swap(比较并交换)的缩写,是一种非阻塞式并发控制技术,用于保证多个线程在修改同一个共享资源时不会出现竞争条件,从而避免了传统锁机制的各种问题。在Java中,CAS主要是通过java.util.concurrent.atomic包下的一些类和方法来实现的,下面我们就来详细了解一下CAS及其在Java中的使用。

在这里插入图片描述

什么是CAS?

CAS是一种非阻塞式并发控制技术,它主要用于解决多个线程同时访问同一个共享资源时可能出现的竞争条件问题。为了保证数据的一致性和正确性,我们通常需要采取同步机制来对共享资源进行加锁。但是,传统的锁机制在高并发场景下会带来严重的性能问题,因为所有线程都需要等待锁的释放才能进行操作,这就会导致大量线程的阻塞和唤醒,进而降低了系统的并发性能。

为了解决这个问题,CAS应运而生。它是一种无锁的同步机制,可以在不使用锁的情况下实现数据的同步和并发控制。CAS的核心思想是:在执行操作之前,先比较当前内存中的值是否等于期望值,如果相等,则执行修改操作;如果不相等,则不执行修改操作,继续进行比较,直到内存中的值与期望值相等为止。这个过程中不会出现线程的阻塞和唤醒,因此可以提高系统的并发性能。

Java中的CAS

在Java中,CAS主要是通过java.util.concurrent.atomic包下的一些类和方法来实现的。这些类和方法提供了一种原子操作的方式,可以保证多个线程同时访问同一个共享资源时不会出现竞争条件。

AtomicBoolean

AtomicBoolean类表示一个布尔类型的原子变量,它提供了一些原子操作方法,例如compareAndSet、getAndSet、weakCompareAndSet等,可以保证对该变量的操作是原子的。

下面是一个示例代码:

  1. import java.util.concurrent.atomic.AtomicBoolean;
  2. public class AtomicBooleanTest {
  3. private static AtomicBoolean flag = new AtomicBoolean(false);
  4. public static void main(String[] args) throws InterruptedException {
  5. Thread t1 = new Thread(() -> {
  6. while (!flag.compareAndSet(false, true)) {
  7. System.out.println(Thread.currentThread().getName() + ": try again");
  8. }
  9. System.out.println(Thread.currentThread().getName() + ": success");
  10. },"Thread-1");
  11. Thread t2 = new Thread(() -> {
  12. while (!flag.compareAndSet(false, true)) {
  13. System.out.println(Thread.currentThread().getName() + ": try again");
  14. }
  15. System.out.println(Thread.currentThread().getName() + ": success");
  16. },"Thread-2");
  17. t1.start();
  18. t2.start();
  19. t1.join();
  20. t2.join();
  21. }
  22. }

在这个例子中,我们创建了一个AtomicBoolean类型的变量flag,并定义了两个线程t1和t2,它们都会不断地尝试将flag的值由false变为true,直到成功为止。如果两个线程同时尝试修改flag的值,只有一个线程能够获得成功,另一个线程会继续尝试,直到成功为止。

AtomicInteger

AtomicInteger类表示一个整型的原子变量,它提供了一些原子操作方法,例如compareAndSet、getAndSet、incrementAndGet等,可以保证对该变量的操作是原子的。

下面是一个示例代码:

  1. import java.util.concurrent.atomic.AtomicInteger;
  2. public class AtomicIntegerTest {
  3. private static AtomicInteger count = new AtomicInteger(0);
  4. public static void main(String[] args) throws InterruptedException {
  5. Thread t1 = new Thread(() -> {
  6. for (int i = 0;i < 10000; i++) {
  7. count.incrementAndGet();
  8. }
  9. },"Thread-1");
  10. Thread t2 = new Thread(() -> {
  11. for (int i = 0; i < 10000; i++) {
  12. count.incrementAndGet();
  13. }
  14. },"Thread-2");
  15. t1.start();
  16. t2.start();
  17. t1.join();
  18. t2.join();
  19. System.out.println("count = " + count.get());
  20. }
  21. }

在这个例子中,我们创建了一个AtomicInteger类型的变量count,并定义了两个线程t1和t2,它们都会对count进行一万次的自增操作。由于AtomicInteger提供的incrementAndGet方法是原子的,因此多个线程同时对count进行自增操作不会出现竞争条件,最终count的值会是正确的。

AtomicReference

AtomicReference类表示一个引用类型的原子变量,它提供了一些原子操作方法,例如compareAndSet、getAndSet、weakCompareAndSet等,可以保证对该变量的操作是原子的。

下面是一个示例代码:

  1. import java.util.concurrent.atomic.AtomicReference;
  2. public class AtomicReferenceTest {
  3. private static class Student{
  4. private String name;
  5. private int age;
  6. public Student(String name, int age) {
  7. this.name = name;
  8. this.age = age;
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public int getAge() {
  14. return age;
  15. }
  16. public void setName(String name) {
  17. this.name = name;
  18. }
  19. public void setAge(int age) {
  20. this.age = age;
  21. }
  22. @Override
  23. public String toString() {
  24. return "Student{" +
  25. "name='" + name + '\'' +
  26. ", age=" + age +
  27. '}';
  28. }
  29. }
  30. private static AtomicReference<Student> student = new AtomicReference<>(new Student("张三", 18));
  31. public static void main(String[] args) {
  32. Student newStudent = new Student("李四", 20);
  33. student.compareAndSet(student.get(), newStudent);
  34. System.out.println(student.get());
  35. }
  36. }

在这个例子中,我们创建了一个AtomicReference类型的变量student,并定义了一个Student类型的对象newStudent。我们通过compareAndSet方法将原子变量student的值从原来的Student对象修改为newStudent对象,由于AtomicReference提供的compareAndSet方法是原子的,因此多个线程同时对student进行修改操作不会出现竞争条件。

总结

CAS是一种非阻塞式的并发控制技术,它可以在不使用锁的情况下实现数据的同步和并发控制,从而提高系统的并发性能。在Java中,CAS主要是通过java.util.concurrent.atomic包下的一些类和方法来实现的,它们提供了一种原子操作的方式,可以保证多个线程同时访问同一个共享资源时不会出现竞争条件。在实际开发中,如果需要对共享资源进行并发控制,建议优先考虑使用CAS技术。

发表评论

表情:
评论列表 (有 0 条评论,129人围观)

还没有评论,来说两句吧...

相关阅读

    相关 CAS 什么?优缺点

    CAS 简单介绍:比较并交换(compareAndSet),将当前工作内存的值与主内存进行比较,如果一致则进行交换,不一致则继续读取主内存最新的值,下面给出 CAS 简单使用的

    相关 什么CAS

    CAS 是 Compare-And-Swap(比较并交换)的缩写,它是一种并发编程中的原子操作,用于实现多线程环境下的数据同步和线程安全。CAS 操作涉及三个主要步骤:比较一个

    相关 什么CAS

    1、什么是CAS CAS : compare and swap 比较和交换。 CAS 在没有锁的情况下,可以保证多个线程对一个值的更新。 ![99cc9c

    相关 什么CAS

    CAS,全称为Compare and Set,即比较-设置。假设有三个操作数: 内存值V、旧的预期值A、要修改的值B,当且仅当预期值A和内存值V相同时,才会将内存值修改为B并返