返回
原子变量及 CAS
后端
2023-12-26 07:10:05
原子变量顾名思义,就是具有原子性的变量。原子性是指变量操作不会被中断,无论有多少线程同时操作该变量,都只能由一个线程对其进行操作。
在 Java 中,原子变量是通过 CAS(Compare-And-Swap)操作来实现的。CAS 操作的基本原理是:比较变量的当前值是否等于预期值,如果是则更新变量的值,否则不更新。
CAS 操作的格式如下:
boolean compareAndSet(int expectedValue, int newValue)
- expectedValue: 预期的值。
- newValue: 如果变量的当前值等于 expectedValue,则将变量的值更新为 newValue。
CAS 操作的实现步骤如下:
- 线程 A 将变量的当前值读入寄存器中。
- 线程 A 将 expectedValue 与寄存器中的值进行比较。
- 如果 expectedValue 等于寄存器中的值,则线程 A 将 newValue 写入寄存器中。
- 线程 A 将寄存器中的值写入变量中。
如果在步骤 2 中,线程 A 发现 expectedValue 不等于寄存器中的值,则说明变量的值已被其他线程修改。此时,线程 A 需要重新获取变量的当前值,并再次执行 CAS 操作。
CAS 操作保证了原子性 ,因为它只允许一个线程对变量进行操作。如果其他线程试图在同一时间访问变量,它们将被阻塞,直到第一个线程完成操作。
CAS 操作的应用场景非常广泛 ,比如:
- 实现锁: CAS 操作可以用来实现锁,从而保证共享资源的独占访问。
- 计数器: CAS 操作可以用来实现计数器,从而保证对共享计数器的并发访问。
- 原子更新: CAS 操作可以用来原子地更新变量的值,从而保证更新操作的正确性。
示例:
import java.util.concurrent.atomic.AtomicInteger;
public class CASDemo {
private static AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args) {
// 创建多个线程,同时对count进行加一操作
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (int j = 0; j < 1000; j++) {
// 使用 CAS 操作对count进行加一操作
count.incrementAndGet();
}
}).start();
}
// 等待所有线程执行完成
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 打印count的最终值
System.out.println("count = " + count.get());
}
}
在上面的示例中,我们使用 CAS 操作来对共享变量 count 进行加一操作。由于 CAS 操作保证了原子性,因此我们可以保证 count 的值始终是正确的。
总结
CAS 操作是一种非常重要的并发编程技术,它可以用来实现原子变量、锁、计数器等并发数据结构。CAS 操作的广泛应用,使得 Java 在处理并发问题时更加高效和可靠。