存在缺陷的代码:
public class DataPropertyIdAndNameRepositoryImpl{
/** 发布标志 */
private volatile boolean publishFlag;
public Integer getStandardId(int dataId, String propertyName) {
if (!publishFlag) {
loadToCache();
}
Integer standardId = 0;
Map<String, Integer> propertyIdMap = propertyIdLocalCache.get(dataId);
if (propertyIdMap != null) {
standardId = propertyIdMap.get(propertyName);
}
return standardId;
}
public synchronized boolean loadToCache() {
try {
DataPropertyIdAndName dataPropertyIdAndName = dataPropertyIdAndNameService
.queryDataPropertyIdAndName();
publishFlag = true;
} catch (Exception e) {
publishFlag = false;
}
return publishFlag;
}
}
存在缺陷的流程:
a. 绿色表示第一个线程,蓝色表示第二个线程。
b. 黄色模块的代码为synchronized标记的代码,并发情况下只会有一个线程执行此方法。
c. 绿色线程执行到紫色模块时,蓝色线程等待进入黄色模块。
d. 蓝色线程执行抛异常,导致publishFlag被置为false。
e. 此时再次有线程进入,判断publishFlag仍为false,因此导致重复不断加载loadToCache.
修复后的代码:
public class DataPropertyIdAndNameRepositoryImpl{
/** 发布标志 */
private volatile boolean publishFlag;
public Integer getStandardId(int dataId, String propertyName) {
if (!publishFlag) {
loadToCache();
}
Integer standardId = 0;
Map<String, Integer> propertyIdMap = propertyIdLocalCache.get(dataId);
if (propertyIdMap != null) {
standardId = propertyIdMap.get(propertyName);
}
return standardId;
}
public synchronized boolean loadToCache() {
try {
// 双检锁
if (publishFlag) {
return publishFlag;
}
DataPropertyIdAndName dataPropertyIdAndName = dataPropertyIdAndNameService.queryDataPropertyIdAndName();
publishFlag = true;
} catch (Exception e) {
publishFlag = false;
}
return publishFlag;
}
}
分享到:
相关推荐
[并发](#并发) * [synchronized](#synchronized) * [synchronized底层原理](#synchronized底层原理) * [synchronized 使用方法](#synchronized-使用方法) * [Synchronized和ReentrantLock的区别](#synchronized...
Lock接口与synchronized关键字在Java并发编程中都是用于实现同步机制的重要工具,但它们在使用方式、功能特性以及灵活性等方面存在一些显著的差异。...然而,在高度竞争的并发场景下,Lock接口可能会表现
高并发编程第三阶段04讲 利用CAS构造一个TryLock自定义显式锁-增强并发情况下.mp4 高并发编程第三阶段05讲 AtomicBoolean源码分析.mp4 高并发编程第三阶段06讲 AtomicLong源码分析.mp4 高并发编程第三阶段07...
接着,深入讲解了Java并发编程的核心API,如synchronized关键字、Lock接口、Condition接口、Semaphore等,帮助读者掌握Java并发编程的基本工具和方法。 除了基础知识和API的讲解,本书还重点介绍了Java并发编程的...
死锁:Java中的死锁,包括如何避免死锁和如何解除死锁。 性能优化:Java中的性能优化,包括JVM参数调优、代码优化、使用并发框架等。 并行计算:Java中的并行计算,包括Fork/Join框架、并行流等。 线程间通信:Java...
此外,本书还提供了有关并发编程的全方位的详细内容,例如限制和同步、死锁和冲突、依赖于状态的操作控制、异步消息传递和控制流、协作交互,以及如何创建基于web的服务和计算型服务。 本书的读者对象是那些希望掌握...
读者将通过使用java.lang.thread类、synchronized和volatile关键字,以及wait、notify和notifyall方法,学习如何初始化、控制和协调并发操作。此外,本书还提供了有关并发编程的全方位的详细内容,例如限制和同步、...
理解自旋锁,死锁与重入锁.mp4 深入理解volatile原理与使用.mp4 JDK5提供的原子类的操作以及实现原理.mp4 Lock接口认识与使用.mp4 手动实现一个可重入锁.mp4 AbstractQueuedSynchronizer(AQS)详解.mp4 使用AQS重写...
面试高级开发的期间整理的面试题目,记录我面试遇到过的并发题目以及答案 目录 并发 常说的并发问题是哪些;资源竞争、死锁、事务、可见性 死锁 如何排查死锁; 产生死锁的必要条件: 如何解决解决死锁; 锁 AQS:...
死锁和解决: 介绍死锁的概念,解释死锁产生的原因和充要条件。 并发编程模型: 介绍不同的并发编程模型,如多生产者多消费者、读者写者、线程池等。 volatile 关键字: 解释 volatile 关键字的作用,探讨如何使用 ...
高并发编程第三阶段04讲 利用CAS构造一个TryLock自定义显式锁-增强并发情况下.mp4 高并发编程第三阶段05讲 AtomicBoolean源码分析.mp4 高并发编程第三阶段06讲 AtomicLong源码分析.mp4 高并发编程第三阶段07...
第17节理解自旋锁,死锁与重入锁00:24:58分钟 | 第18节深入理解volatile原理与使用00:28:30分钟 | 第19节JDK5提供的原子类的操作以及实现原理00:27:10分钟 | 第20节Lock接口认识与使用00:19:54分钟 | 第21节手动...
,如何避免线程死锁 线程的 run()和 start()有什么区别? 什么是 Callable 和 Future? 线程的调度策略 sleep() 和 wait() 有什么区别? 什么是线程同步和线程互斥,有哪几种实现方式? Java 线程数过多会造成什么...
读者将通过使用java.lang.thread类、synchronized和volatile关键字,以及wait、notify和notifyall方法,学习如何初始化、控制和协调并发操作。此外,本书还提供了有关并发编程的全方位的详细内容,例如限制和同步、...
6)用 Java 编程一个会导致死锁的程序,你将怎么解决? 7) 什么是原子操作,Java 中的原子操作是什么? 8) Java 中的 volatile 关键是什么作用?怎样使用它?在 Java 中它跟 synchronized 方法有什么不同? 9) 什么...
13.4 在synchronized和ReentrantLock之间进行选择234 13.5 读-写锁235 第14章 构建自定义的同步工具238 14.1 状态依赖性的管理238 14.1.1 示例:将前提条件的失败传递给调用者240 14.1.2 示例:通过轮询与休眠...
(1)【高并发】优化加锁方式时竟然死锁了!!》 (2)讲讲什么是缓存穿透?击穿?雪崩?如何解决? (3)Java中提供了synchronized,为什么还要提供Lock呢? 5、系统架构篇 (1) 高并发分布式锁架构解密,不是所有的...
第17节理解自旋锁,死锁与重入锁00:24:58分钟 | 第18节深入理解volatile原理与使用00:28:30分钟 | 第19节JDK5提供的原子类的操作以及实现原理00:27:10分钟 | 第20节Lock接口认识与使用00:19:54分钟 | 第21节手动...
第17节理解自旋锁,死锁与重入锁00:24:58分钟 | 第18节深入理解volatile原理与使用00:28:30分钟 | 第19节JDK5提供的原子类的操作以及实现原理00:27:10分钟 | 第20节Lock接口认识与使用00:19:54分钟 | 第21节手动...