Java并发编程:深入解析AtomicInteger和CAS无锁算法
作者:书友34043247 | 来源:互联网 | 2024-11-12 16:40
在多线程并发环境中,普通变量的操作往往是线程不安全的。本文通过一个简单的例子,展示了如何使用AtomicInteger类及其核心的CAS无锁算法来保证线程安全。
### 深入解析 AtomicInteger
在多线程并发环境下,普通的成员变量操作可能会导致线程不安全。例如,假设我们有两个线程,每个线程对一个整数进行1000次自增操作,最终的结果应该是1000。然而,由于多线程的并发执行,结果往往不是1000。
#### 示例代码
```java
package atomic;
public class AtomicIntegerTest extends Thread {
private Integer count = 0;
@Override
public void run() {
for (int i = 1; i <= 500; i++) {
count++;
}
System.out.println("count的值是:" + count);
}
public static void main(String[] args) {
AtomicIntegerTest a = new AtomicIntegerTest();
Thread t1 = new Thread(a);
Thread t2 = new Thread(a);
t1.start();
t2.start();
}
}
```
运行上述代码,最终的结果会小于1000,因为两个线程可能同时修改了变量的值。
### 使用 AtomicInteger 保证线程安全
`AtomicInteger` 类提供了一种原子性操作变量的方法,其核心是 CAS 无锁算法。CAS 算法是一种基于乐观锁的实现方法,可以在不使用锁的情况下完成原子性操作。
#### CAS 算法原理
CAS 算法的主要原理是在修改变量时,进入一个 `while` 循环,不断尝试 `compareAndSet()` 方法,即不断地比较内存值和期望值,如果相等则修改,否则返回 `false`。当值修改成功后,循环结束。
#### 修改后的示例代码
```java
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicIntegerTest2 extends Thread {
private AtomicInteger count = new AtomicInteger(0);
@Override
public void run() {
for (int i = 1; i <= 500; i++) {
count.getAndIncrement();
}
System.out.println("count的值是:" + count);
}
public static void main(String[] args) {
AtomicIntegerTest2 a = new AtomicIntegerTest2();
Thread t1 = new Thread(a);
Thread t2 = new Thread(a);
t1.start();
t2.start();
}
}
```
运行修改后的代码,最终的结果是1000,说明 `AtomicInteger` 成功保证了数据的原子性操作。
### 线程安全的其他方法
除了 `AtomicInteger`,常见的线程安全方法还包括:
1. **同步锁或同步代码块**
2. **互斥锁或重入锁**
这些方法都是利用锁来解决线程并发问题,属于悲观锁的方式。`synchronized` 关键字在 JDK 1.6 之后进行了优化,性能与 `Lock` 锁相当。
### CAS 算法的底层实现
`AtomicInteger` 的底层实现依赖于 `Unsafe` 类,具体实现如下:
```java
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersiOnUID= 6214790243416807050L;
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) {
throw new Error(ex);
}
}
private volatile int value;
}
```
`Unsafe` 是 CAS 的核心类,负责具体的底层实现。`valueOffset` 变量表示 `value` 在内存中的起始偏移量。`value` 使用 `volatile` 修饰,保证了内存的可见性。
#### `getAndIncrement()` 方法的实现
```java
public final int getAndIncrement() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return current;
}
}
```
该方法进入一个无限循环,不断比较内存值和期望值,如果相等则修改,否则继续尝试。
### 总结
`AtomicInteger` 类通过 CAS 无锁算法实现了高效的线程安全操作。在并发量不高的情况下,CAS 算法能够显著提高性能,避免了传统锁带来的开销。
推荐阅读
-
本文介绍了在 Java 编程中遇到的一个常见错误:对象无法转换为 long 类型,并提供了详细的解决方案。 ...
[详细]
蜡笔小新 2024-11-13 10:57:24
-
本文详细介绍了Java反射机制的基本概念、获取Class对象的方法、反射的主要功能及其在实际开发中的应用。通过具体示例,帮助读者更好地理解和使用Java反射。 ...
[详细]
蜡笔小新 2024-11-13 16:08:08
-
-
本文深入探讨了CAS(Compare-and-Swap)机制,分析了其作为传统锁的替代方案在并发控制中的优势与原理。CAS通过原子操作确保数据的一致性,避免了传统锁带来的性能瓶颈和死锁问题。文章详细解析了CAS的工作机制,并结合实际应用场景,展示了其在高并发环境下的高效性和可靠性。 ...
[详细]
蜡笔小新 2024-11-09 15:45:07
-
本文节选自《NLTK基础教程——用NLTK和Python库构建机器学习应用》一书的第1章第1.2节,作者Nitin Hardeniya。本文将带领读者快速了解Python的基础知识,为后续的机器学习应用打下坚实的基础。 ...
[详细]
蜡笔小新 2024-11-13 21:23:34
-
本文详细介绍了Java并发工具包中的核心类AQS(AbstractQueuedSynchronizer),包括其基本概念、数据结构、源码分析及核心方法的实现。 ...
[详细]
蜡笔小新 2024-11-13 15:40:34
-
Spring – Bean Life Cycle ...
[详细]
蜡笔小新 2024-11-13 13:24:40
-
DAO(Data Access Object)模式是一种用于抽象和封装所有对数据库或其他持久化机制访问的方法,它通过提供一个统一的接口来隐藏底层数据访问的复杂性。 ...
[详细]
蜡笔小新 2024-11-13 12:25:33
-
本文将深入探讨Java中线程的三种主要实现方式,包括继承Thread类、实现Runnable接口和实现Callable接口,并分析它们之间的异同及其应用场景。 ...
[详细]
蜡笔小新 2024-11-12 14:31:23
-
字节流抽象类InputStream和OutputStream是字节流的顶级父类所有的字节输入流都继承自InputStream,所有的输出流都继承子OutputStreamInput ...
[详细]
蜡笔小新 2024-11-12 14:07:25
-
深入解析 Synchronized 锁的升级机制及其在并发编程中的应用 ...
[详细]
蜡笔小新 2024-11-11 13:09:38
-
线程能否先以安全方式获取对象,再进行非安全发布? ...
[详细]
蜡笔小新 2024-11-09 09:21:53
-
本文详细介绍了JVM钩子函数的多种应用场景,包括正常关闭、异常关闭和强制关闭。通过具体示例和代码演示,帮助读者更好地理解和应用这一机制。适合对Java编程和JVM有一定基础的开发者阅读。 ...
[详细]
蜡笔小新 2024-11-13 18:34:48
-
原文网址:https:www.cnblogs.comysoceanp7476379.html目录1、AOP什么?2、需求3、解决办法1:使用静态代理4 ...
[详细]
蜡笔小新 2024-11-12 14:40:40
-
这期内容当中小编将会给大家带来有关如何在Java中使用DButils类,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。D ...
[详细]
蜡笔小新 2024-11-12 13:46:11
-
深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案 ...
[详细]
蜡笔小新 2024-11-09 19:04:36
-
书友34043247
这个家伙很懒,什么也没留下!