存在缺陷的代码:
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;
}
}
分享到:
相关推荐
在Java的HashMap中,多线程并发环境下的扩容操作可能会引发死锁问题。这主要发生在JDK 1.7版本,因为其扩容机制采用了头插法。以下详细解释这个问题及其解决方案。 首先,HashMap的扩容机制是在容量达到阈值时触发...
在某些情况下,`synchronized`关键字使用的锁是“隐形”的,即它默认使用的是当前对象实例作为锁。这意味着如果在同一个对象上定义了两个`synchronized`方法,它们实际上是互斥的,因为它们都在争夺同一个锁。通过...
在Java编程语言中,`synchronized`关键字是一个非常重要的并发控制机制,用于保证多线程环境下的数据一致性。本文将深入解析`synchronized`的工作原理、使用方式以及它在并发编程中的重要性。通过分析提供的源码,...
1. 线程安全:并发可能导致数据竞争、死锁等问题,需要精心设计和管理线程间的同步。 2. 资源消耗:创建和管理线程需要额外的系统资源,过多的并发可能导致资源浪费。 3. 难以调试:并发问题往往难以定位,因为错误...
`synchronized`关键字是Java提供的一种内置锁机制,用于控制对共享资源的并发访问,从而避免线程安全问题,包括死锁。本文将深入探讨如何使用`synchronized`来解决Java中的死锁问题。 首先,我们需要理解死锁的四个...
1. 成功案例:正确使用`synchronized`,确保共享资源在并发环境下的安全访问,避免数据异常。 2. 失败案例:未使用或错误使用`synchronized`,导致线程安全问题,如死锁、竞态条件等。 五、线程安全问题 1. 死锁:...
但是,在某些情况下,可能需要在一定时期内霸占某个对象的钥匙,这时可以使用 Synchronized 代码块。 Java 锁机制 Synchronized 的优点 Java 锁机制 Synchronized 的优点是可以解决多线程并发访问共享资源时可能...
通过`synchronized`,我们可以控制对共享资源的访问,避免并发问题,如数据竞争和死锁。本文将详细探讨`synchronized`的关键特性、用法以及它在实际开发中的应用。 1. **synchronized的两种使用方式** - **方法...
Java并发编程中的Synchronized关键字是实现线程安全的关键工具,它提供了锁机制,确保了多线程环境下的数据一致性与安全性。以下将详细介绍Synchronized的使用及其实现原理。 一、Synchronized基本使用 1. 修饰...
在Java编程中,死锁是并发编程中一个重要的概念,它发生在两个或多个线程相互等待对方释放资源,导致它们都无法继续执行的情况。这个例子中,我们将会深入探讨死锁的产生、识别以及如何避免它。 首先,让我们理解...
"Java 多线程与并发(4-26)-关键字- synchronized详解" Java 多线程与并发中的 synchronized 关键字是实现同步块的互斥访问和线程的阻塞及唤醒等工作的重要工具。下面将对 synchronized 关键字进行详细分析。 ...
Java中的`synchronized`关键字是多线程编程中的一个重要概念,用于控制并发访问共享资源,以保证数据的一致性和完整性。这个关键词提供了互斥锁机制,防止多个线程同时执行同一段代码,确保了线程安全。 一、`...
在Java编程语言中,`synchronized`关键字是一个重要的并发控制机制,用于确保多线程环境下的数据一致性。本文将深入探讨`synchronized`的几种使用示例,包括方法加锁、代码块加锁(针对`this`和对象)以及静态方法...
Java 中的 synchronized 关键字是用于解决多线程并发问题的重要工具之一。它可以被用于方法、代码块和变量上,以实现对共享资源的互斥访问控制。本文将对 Java 中的 synchronized 用法进行详细的解释和分析。 一、...
- Java的`synchronized`是可重入的,意味着一个线程在已经获得某个对象锁的情况下,还可以再次请求该锁(但计数器会递增),不会造成死锁。 6. **synchronized与 volatile 的区别**: - `volatile`主要保证变量的...
这种情况下,两个线程都在等待对方释放锁,形成了典型的死锁状态。为了深入理解,我们需要关注以下几个关键概念: - **线程优先级**(prio):虽然线程优先级在这里并不是造成死锁的直接原因,但优先级设置不恰当...
描述中反复提到“java并发编程艺术”,这暗示书中将详细介绍如何优雅地设计和管理线程,避免常见的并发问题,如死锁、竞态条件和活锁。 在Java中,同步是控制多个线程访问共享资源的方式,主要通过`synchronized`...
`synchronized`是Java中的一个关键字,用于实现线程同步,它主要解决多线程环境下共享资源的并发访问问题,防止出现数据不一致的情况。当多个线程试图同时访问同一块代码时,`synchronized`会确保同一时间只有一个...
在Java编程中,死锁(DeadLock)是一个重要的并发控制问题,它发生在两个或多个线程互相持有对方需要的资源并等待对方释放时,导致所有线程都无法继续执行的情况。死锁是多线程编程中需要特别注意和避免的问题,因为...