简介与作用:
AtomicReference
是Java中的一个原子类,它的主要作用是提供了一种原子操作的方式来更新对象的引用。它通常用于多线程环境下,用来解决并发访问共享对象时可能出现的竞态条件问题。
(实际开发中用于某个数据模型更新,确保一致性和线程安全,多个线程同时更新只有一个线程能够成功执行,其它线程需要等待后继续尝试更新,例如:计算总分(获取答题表分数)并更新到答案表中)
- 原子性更新引用: AtomicReference可以确保在多线程环境下,对对象引用的更新操作是原子的,即要么更新成功,要么失败,不存在中间状态。这有助于避免多线程同时修改同一对象引用时可能出现的数据不一致性问题。
- 解决竞态条件问题: 在多线程编程中,如果多个线程同时尝试更新共享对象的引用,可能会导致不可预测的结果。使用AtomicReference可以防止这种情况发生,确保只有一个线程能够成功更新引用。
- 实现非阻塞算法: AtomicReference可以用于实现非阻塞算法,这些算法通常比基于锁的算法具有更好的性能和可伸缩性,特别是在高并发情况下。
- 并发数据结构的实现: AtomicReference常常用于实现各种并发数据结构,如并发队列、并发映射等,以确保对这些数据结构的操作是线程安全的。
测试:
原子引用:
原子引用是一种保证在多线程环境下对引用类型的原子操作的机制。这意味着对原子引用的操作(如更新、比较并交换等)在多线程环境中是线程安全的,它们会以原子方式执行,即这些操作在执行过程中不会被其他线程打断。
@Test
public void cs3() throws InterruptedException {
AtomicReference<Integer> atomicRef = new AtomicReference<>(0);
int numThreads = 10;
int numIncrements = 1000;
// 创建一个线程池,包含10个线程
ExecutorService executorService = Executors.newFixedThreadPool(numIncrements);
// 测试原子引用
// 每个线程对AtomicReference进行1000次增量操作
for (int i = 0; i < numThreads; i++) {
executorService.submit(() -> {
for (int j = 0; j < numIncrements; j++) {
atomicRef.updateAndGet(value -> value + 1);
System.out.println(Thread.currentThread().getName() + " : " + atomicRef.get());
}
});
}
executorService.shutdown();
executorService.awaitTermination(10, TimeUnit.SECONDS);// 等待线程池执行结束
// 输出最终的值
System.out.println("AtomicReference的值: " + atomicRef.get());
}
@Test
public void cs4() throws InterruptedException {
final Integer[] cs = {0};
int numThreads = 10;
int numIncrements = 1000;
// 创建一个线程池,包含10个线程
ExecutorService executorService = Executors.newFixedThreadPool(numThreads);
// 每个线程对int进行1000次增量操作
for (int i = 0; i < numThreads; i++) {
executorService.submit(() -> {
for (int j = 0; j < numIncrements; j++) {
cs[0] = cs[0] + 1;
System.out.println(cs[0]);
}
});
}
executorService.shutdown();
executorService.awaitTermination(10, TimeUnit.SECONDS);// 等待线程池执行结束
// 输出最终的值
System.out.println("线程不安全原子的值: " + cs[0]);
}