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等,能够保障对该变量的操作是原子的。
上面是一个示例代码:
import java.util.concurrent.atomic.AtomicBoolean;public class AtomicBooleanTest { private static AtomicBoolean flag = new AtomicBoolean(false); public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { while (!flag.compareAndSet(false, true)) { System.out.println(Thread.currentThread().getName() + ": try again"); } System.out.println(Thread.currentThread().getName() + ": success"); },"Thread-1"); Thread t2 = new Thread(() -> { while (!flag.compareAndSet(false, true)) { System.out.println(Thread.currentThread().getName() + ": try again"); } System.out.println(Thread.currentThread().getName() + ": success"); },"Thread-2"); t1.start(); t2.start(); t1.join(); t2.join(); }}
在这个例子中,咱们创立了一个AtomicBoolean类型的变量flag,并定义了两个线程t1和t2,它们都会一直地尝试将flag的值由false变为true,直到胜利为止。如果两个线程同时尝试批改flag的值,只有一个线程可能获得成功,另一个线程会持续尝试,直到胜利为止。
AtomicInteger
AtomicInteger类示意一个整型的原子变量,它提供了一些原子操作方法,例如compareAndSet、getAndSet、incrementAndGet等,能够保障对该变量的操作是原子的。
上面是一个示例代码:
import java.util.concurrent.atomic.AtomicInteger;public class AtomicIntegerTest { private static AtomicInteger count = new AtomicInteger(0); public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { for (int i = 0;i < 10000; i++) { count.incrementAndGet(); } },"Thread-1"); Thread t2 = new Thread(() -> { for (int i = 0; i < 10000; i++) { count.incrementAndGet(); } },"Thread-2"); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("count = " + count.get()); }}
在这个例子中,咱们创立了一个AtomicInteger类型的变量count,并定义了两个线程t1和t2,它们都会对count进行一万次的自增操作。因为AtomicInteger提供的incrementAndGet办法是原子的,因而多个线程同时对count进行自增操作不会呈现竞争条件,最终count的值会是正确的。
AtomicReference
AtomicReference类示意一个援用类型的原子变量,它提供了一些原子操作方法,例如compareAndSet、getAndSet、weakCompareAndSet等,能够保障对该变量的操作是原子的。
上面是一个示例代码:
import java.util.concurrent.atomic.AtomicReference;public class AtomicReferenceTest { private static class Student{ private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } } private static AtomicReference<Student> student = new AtomicReference<>(new Student("张三", 18)); public static void main(String[] args) { Student newStudent = new Student("李四", 20); student.compareAndSet(student.get(), newStudent); System.out.println(student.get()); }}
在这个例子中,咱们创立了一个AtomicReference类型的变量student,并定义了一个Student类型的对象newStudent。咱们通过compareAndSet办法将原子变量student的值从原来的Student对象批改为newStudent对象,因为AtomicReference提供的compareAndSet办法是原子的,因而多个线程同时对student进行批改操作不会呈现竞争条件。
总结
CAS是一种非阻塞式的并发控制技术,它能够在不应用锁的状况下实现数据的同步和并发管制,从而进步零碎的并发性能。在Java中,CAS次要是通过java.util.concurrent.atomic包下的一些类和办法来实现的,它们提供了一种原子操作的形式,能够保障多个线程同时拜访同一个共享资源时不会呈现竞争条件。在理论开发中,如果须要对共享资源进行并发管制,倡议优先思考应用CAS技术。