为什么java.util.HashMap.getEntry可以阻止我的程序?

时间:2010-08-07 06:35:15

标签: multithreading thread-safety java threadpool

我的程序被阻止了,我用jstack命令分析,下面的线程拿了锁“0x0000000603f02ae0”,其他线程无法获取锁。
我等了至少一个小时,但线程没有解锁,我的问题是为什么thread'state正在运行,并停在java.util.HashMap.getEntry(HashMap.java:347)?它是oracle(sun)JDK的bug?

我的jdk版本:
java版“1.6.0_21”
Java(TM)SE运行时环境(版本1.6.0_21-b06)
Java HotSpot(TM)64位服务器VM(版本17.0-b16,混合模式)

主题信息:
“PandoraScheduleTrigger-thread-5”prio = 10 tid = 0x00000000443b0800 nid = 0x5804 runnable [0x0000000043722000]    java.lang.Thread.State:RUNNABLE     在java.util.HashMap.getEntry(HashMap.java:347)     在java.util.HashMap.containsKey(HashMap.java:335)     在com.youlongqingfeng.pandora.context.ArmiesContext._getArmy(ArmiesContext.java:239)     在com.youlongqingfeng.pandora.context.ArmiesContext.getArmiesByCityId(ArmiesContext.java:169)     在com.youlongqingfeng.pandora.model.City.getTotalApplianceMap(City.java:4519)     在com.youlongqingfeng.pandora.model.City.calculateMemoryResource(City.java:4636)     在com.youlongqingfeng.pandora.model.City.buildTaskFinish(City.java:1089)     在com.youlongqingfeng.pandora.map.unit.ZhouMapResourceUnit.buildTaskFinish(ZhouMapResourceUnit.java:1618)      - 已锁定< 0x0000000603f02ae0> (com.youlongqingfeng.pandora.map.unit.ZhouMapResourceUnit)     在com.youlongqingfeng.pandora.trigger.BuildTrigger.innerRun(BuildTrigger.java:39)     在com.youlongqingfeng.gameserver.utils.threadpool.CancelTrigger.run(CancelTrigger.java:34)

阻止的线程转储:

“PandoraScheduleTrigger-thread-3”prio = 10 tid = 0x0000000044c7c000 nid = 0x5802等待监视​​器输入[0x0000000043520000]    java.lang.Thread.State:BLOCKED(在对象监视器上)     at com.youlongqingfeng.pandora.map.unit.ZhouMapResourceUnit.armiesGroupReturnBack(ZhouMapResourceUnit.java:2279)      - 等待锁定< 0x0000000603f02ae0> (com.youlongqingfeng.pandora.map.unit.ZhouMapResourceUnit)     在com.youlongqingfeng.pandora.trigger.ArmyGroupArrivedTrigger.innerRun(ArmyGroupArrivedTrigger.java:53)     在com.youlongqingfeng.gameserver.utils.threadpool.CancelTrigger.run(CancelTrigger.java:34)     at java.util.concurrent.Executors $ RunnableAdapter.call(Executors.java:441)     at java.util.concurrent.FutureTask $ Sync.innerRun(FutureTask.java:303)     在java.util.concurrent.FutureTask.run(FutureTask.java:138)     at java.util.concurrent.ScheduledThreadPoolExecutor $ ScheduledFutureTask.access $ 301(ScheduledThreadPoolExecutor.java:98)     at java.util.concurrent.ScheduledThreadPoolExecutor $ ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:207)     at java.util.concurrent.ThreadPoolExecutor $ Worker.runTask(ThreadPoolExecutor.java:886)     at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:908)     在java.lang.Thread.run(Thread.java:619)

谢谢。

4 个答案:

答案 0 :(得分:5)

实际上,您可以使用ConcurrentHashMap而不是HashMap。 当不同的线程在循环中访问地图时,HashMap将进入阻塞状态。可以有效地使用ConcurrentHashMap。它同步且高效。它不会锁定整个Map,只会锁定当前访问的存储桶。

答案 1 :(得分:3)

需要考虑的一些事项:

  • 您使用的是HashMap,它本身未同步。您是否在所有接入点同步对代码中的地图的访问?如果不这样做,则对地图的并发访问可能会破坏内部数据,从而导致不可预测的行为。

  • 一个线程有锁,另一个线程试图获取它。你是否有可能遇到2个锁定的情况,其中2个线程正在等待另一个线程释放锁定之前需要的锁定? (线程1锁定a,等待b +线程2锁定b等待 - >死锁。)

答案 2 :(得分:2)

你确定线程停在 getEntry 吗?状态可运行,所以我想它已经运行了?你在这一步抓住了jstack,就是这样。我想在 ZhouMapResourceUnit.buildTaskFinish 下面有一些无限循环,并且永远不会释放锁。

答案 3 :(得分:0)

如果有多个线程,则使用Hashtable;如果只有一个线程,则使用HashMap。