multithreading - HashMap 线程的这种用法安全吗?
问题描述
我碰巧在一个使用mapperdao 库的项目中工作。
有时,它会引发异常,表明该库不是线程安全的。我不知道为什么。
问题发生在这段代码中:
type CacheKey = (Class[_], LazyLoad) private val classCache = new scala.collection.mutable.HashMap[CacheKey, (Class[_], Map[String, ColumnInfoRelationshipBase[_, Any, Any, Any]])] def proxyFor[ID, T](构造:T 与 Persisted,实体:EntityBase[ID,T],lazyLoad:LazyLoad,vm:ValuesMap):T 与 Persisted = { (...) val key = (clz,lazyLoad) // 获取缓存的代理类或生成它 val (proxyClz, methodToCI) = classCache.synchronized { classCache.get(key).getOrElse { val 方法 = lazyRelationships.map(ci => ci.getterMethod.getOrElse( throw new IllegalStateException("请在实体 %s 上定义 getter 方法。%s".format(entity.getClass.getName, ci.column)) ).getter 方法 )。设置 如果 (methods.isEmpty) throw new IllegalStateException("不能延迟加载没有为关系声明任何 getter 的类。实体:%s".format(clz)) val proxyClz = createProxyClz(constructedClz, clz, 方法) val methodToCI =lazyRelationships.map { 词=> (ci.getterMethod.get.getterMethod.getName, ci.asInstanceOf[ColumnInfoRelationshipBase[T, Any, Any, Any]]) }.toMap val r = (proxyClz, methodToCI) classCache.put(key, r) r } } val 实例化器 = objenesis.getInstantiatorOf(proxyClz) val instance = instantiator.newInstance.asInstanceOf[DeclaredIds[ID] with T with MethodImplementation[T with Persisted]] (...) }
instantiator.newInstance
抛出java.lang.NoClassDefFoundError
一个类,该类应该被动态编译并将其名称放入映射中。
这段代码对我来说似乎是线程安全的,因为地图上的任何操作都是在同步块中执行的。我想不出一个场景,当地图返回一个尚未生成和编译的类名时。我错过了什么吗?
另一种解释是该类已编译,但对当前的类加载器不可见。我不知道这是怎么发生的,以及为什么偶尔会发生这种情况。
更新:跟踪看起来像:
java.lang.NoClassDefFoundError:无法初始化类 com.mypackage.MyClass_$2 在 sun.reflect.GeneratedSerializationConstructorAccessor57.newInstance(未知来源) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:423) 在 org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:56) 在 com.googlecode.mapperdao.lazyload.LazyLoadManager.proxyFor(LazyLoadManager.scala:63) 在 com.googlecode.mapperdao.jdbc.impl.MapperDaoImpl.lazyLoadEntity(MapperDaoImpl.scala:338) 在 com.googlecode.mapperdao.jdbc.impl.MapperDaoImpl.$anonfun$toEntities$5(MapperDaoImpl.scala:301) 在 com.googlecode.mapperdao.internal.EntityMap.$anonfun$get$1(EntityMap.scala:46)
更新2:我终于找到了问题的根本原因。这确实是一个并发问题,但不是我粘贴的代码。它在MImpl 类中。这里发生的是动态生成的类被正确编译,但由于MImpl 类中的并发问题,它的初始化偶尔会失败。下次代码尝试实例化类时,JVM 会抛出 NoClassDefFoundException。
解决方案
推荐阅读
- django - Django 和 nginx 以及 gunicorn 和 docker compose - 配置 URL
- c# - 任务在运行时被取消,我的程序无法继续运行
- mysql - nginx 504,无法连接mysql
- r - 尝试绘制多个数据集时出现 ggsurvplot 错误
- asp.net - 如何使用 httpclient 发布数据或使用 Web api
- python - 将列表中的数字相乘 - python 列表索引超出范围
- oracle-sqldeveloper - 与 SQLDeveloper 建立连接时无法选择 postgreSQL 数据库
- php - 插入到当前表并更新到另一个表php
- ios - 在 coremltools 转换中指定 swift 版本
- amazon-web-services - 在 ALB 后面的 AWS EBS 上终止 WebSocket 连接