Java并发中的原子类详细代码实例
作者:014-code
Java中提供了一些原子类,原子类包装了一个变量,并且提供了一系列对变量进行原子性操作的方法,这篇文章主要介绍了Java并发中原子类的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
1. 为什么需要原子类
多线程环境下,有个常见问题:
public class Counter {
private int count = 0;
public void increment() {
count++;
}
}
count++ 看似一行代码,实际分三步:
- 读取 count 的值
- 加 1
- 写回 count
多线程下可能发生:
线程A:读取 count=0
线程B:读取 count=0
线程A:count=1,写回
线程B:count=1,写回 // 线程A的结果被覆盖了
最终 count=1,但实际应该等于 2。
2. 解决办法
synchronized 加锁
public synchronized void increment() {
count++;
}
缺点:性能差,每次只能一个线程进入。
原子类
private AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet();
}
一行搞定,性能比 synchronized 高很多。
3. 常用原子类
AtomicInteger
AtomicInteger count = new AtomicInteger(0); // 加1 count.incrementAndGet(); // ++i count.getAndIncrement(); // i++ // 减1 count.decrementAndGet(); // --i count.getAndDecrement(); // i-- // 加任意值 count.addAndGet(5); // 获取值 int value = count.get(); // 设置值 count.set(100); // CAS 操作 count.compareAndSet(100, 200); // 如果当前值是100,则设置为200
AtomicLong
和 AtomicInteger 用法一样,只是类型不同:
AtomicLong count = new AtomicLong(0); count.incrementAndGet();
AtomicBoolean
AtomicBoolean flag = new AtomicBoolean(false); // 设为 true flag.set(true); // CAS 操作 flag.compareAndSet(false, true);
AtomicReference
用来原子更新对象:
AtomicReference<User> userRef = new AtomicReference<>();
User user1 = new User("张三", 20);
User user2 = new User("李四", 25);
userRef.set(user1);
userRef.compareAndSet(user1, user2); // 如果当前是 user1,则改为 user2
4. 数组原子类
// 数组中某个元素原子操作
AtomicIntegerArray arr = new AtomicIntegerArray(new int[]{1, 2, 3});
arr.getAndAdd(0, 10); // 第一个元素加10
int value = arr.get(0); // 获取第一个元素
5. 累加器
jdk8 新增的,比 AtomicInteger 性能更高,专门用于累加场景:
LongAdder count = new LongAdder(); count.add(1); count.increment(); long value = count.sum();
内部原理是把一个值拆成多个 Cell,减少竞争。适合高并发场景下的累加。
// AtomicInteger vs LongAdder // 低并发:两者差不多 // 高并发:LongAdder 性能更好
6. 实战示例
计数器
public class PageViewCounter {
private AtomicInteger count = new AtomicInteger(0);
public void addView() {
count.incrementAndGet();
}
public int getViews() {
return count.get();
}
}
防止重复提交
public class SubmitService {
private AtomicBoolean submitting = new AtomicBoolean(false);
public void submit() {
// 如果已经在提交中,直接返回
if (!submitting.compareAndSet(false, true)) {
return;
}
try {
// 业务逻辑
doSubmit();
} finally {
submitting.set(false);
}
}
}
配置更新
public class ConfigHolder {
private AtomicReference<Config> configRef = new AtomicReference<>();
public void updateConfig(Config newConfig) {
configRef.updateAndGet(old -> newConfig);
}
public Config getConfig() {
return configRef.get();
}
}
7. 总结
| 类 | 用途 |
|---|---|
| AtomicInteger | 整数原子操作 |
| AtomicLong | 长整数原子操作 |
| AtomicBoolean | 布尔原子操作 |
| AtomicReference | 对象引用原子操作 |
| AtomicIntegerArray | 整数数组原子操作 |
| LongAdder | 高并发累加,比 AtomicLong 性能更好 |
什么时候用:
- 需要保证多线程安全地修改一个值时
- 简单计数、状态标记等场景
- 比 synchronized 性能更好
到此这篇关于Java并发中原子类的文章就介绍到这了,更多相关Java并发原子类内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
