为什么 java.util.HashMap.getEntry 会阻塞我的程序?
我的程序被阻塞了,我用jstack Commander分析,下面的线程拿了锁“0x0000000603f02ae0”,其他线程拿不到锁。
我等了至少一小时,但线程没有解锁,我的问题是为什么线程状态为 RUNNING,并停止在 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 可运行 [0x0000000043722000] java.lang.Thread.State:可运行 在 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) 在 java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441) 在 java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) 在 java.util.concurrent.FutureTask.run(FutureTask.java:138) 在 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98) 在java.util.concurrent.ScheduledThreadPoolExecutor $ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:207) 在 java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 在 java.lang.Thread.run(Thread.java:619)
谢谢。
my program had been blocked , I used the jstack commander to analyze, the following thread took the lock "0x0000000603f02ae0" , and others threads couldn't fetch the lock.
I had waited at least one hour, but the thread didn't unlock , my question is why the thread'state is RUNNING, and stop at java.util.HashMap.getEntry(HashMap.java:347) ? it is oracle(sun) JDK's bug ?
my jdk version :
java version "1.6.0_21"
Java(TM) SE Runtime Environment (build 1.6.0_21-b06)
Java HotSpot(TM) 64-Bit Server VM (build 17.0-b16, mixed mode)
The thread info:
"PandoraScheduleTrigger-thread-5" prio=10 tid=0x00000000443b0800 nid=0x5804 runnable [0x0000000043722000]
java.lang.Thread.State: RUNNABLE
at java.util.HashMap.getEntry(HashMap.java:347)
at java.util.HashMap.containsKey(HashMap.java:335)
at com.youlongqingfeng.pandora.context.ArmiesContext._getArmy(ArmiesContext.java:239)
at com.youlongqingfeng.pandora.context.ArmiesContext.getArmiesByCityId(ArmiesContext.java:169)
at com.youlongqingfeng.pandora.model.City.getTotalApplianceMap(City.java:4519)
at com.youlongqingfeng.pandora.model.City.calculateMemoryResource(City.java:4636)
at com.youlongqingfeng.pandora.model.City.buildTaskFinish(City.java:1089)
at com.youlongqingfeng.pandora.map.unit.ZhouMapResourceUnit.buildTaskFinish(ZhouMapResourceUnit.java:1618)
- locked <0x0000000603f02ae0> (a com.youlongqingfeng.pandora.map.unit.ZhouMapResourceUnit)
at com.youlongqingfeng.pandora.trigger.BuildTrigger.innerRun(BuildTrigger.java:39)
at com.youlongqingfeng.gameserver.utils.threadpool.CancelTrigger.run(CancelTrigger.java:34)
Blocked thread dump:
"PandoraScheduleTrigger-thread-3" prio=10 tid=0x0000000044c7c000 nid=0x5802 waiting for monitor entry [0x0000000043520000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.youlongqingfeng.pandora.map.unit.ZhouMapResourceUnit.armiesGroupReturnBack(ZhouMapResourceUnit.java:2279)
- waiting to lock <0x0000000603f02ae0> (a com.youlongqingfeng.pandora.map.unit.ZhouMapResourceUnit)
at com.youlongqingfeng.pandora.trigger.ArmyGroupArrivedTrigger.innerRun(ArmyGroupArrivedTrigger.java:53)
at 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)
at 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)
at java.lang.Thread.run(Thread.java:619)
thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
实际上,您可以使用 ConcurrentHashMap 而不是 HashMap。
当不同的线程以循环或其他方式访问该映射时,HashMap 将进入阻塞状态。可以有效地使用ConcurrentHashMap。它是同步且高效的。它不会锁定完整的Map,它只是锁定当前访问的bucket。
Actually, you could have used ConcurrentHashMap instead of HashMap.
HashMap will run into block state when different threads access the map in a loop or something. A ConcurrentHashMap can be used effectively. It is synchronized and efficient. It does not lock the complete Map, it just locks the current bucket which is accessed.
需要考虑的一些事情:
您正在使用
HashMap
,它本身并不同步。您是否在所有访问点同步代码中对地图的访问?如果您没有这样做,对映射的并发访问可能会损坏内部数据,从而导致不可预测的行为。一个线程拥有锁,另一个线程正在尝试获取它。是否有可能遇到这样一种情况:涉及 2 个锁,其中 2 个线程正在等待另一个线程释放它们所需的锁,然后再释放它们锁定的锁? (线程 1 锁定 a,等待 b + 线程 2 锁定 b 等待 a -> 死锁。)
Some things to consider:
you are using
HashMap
, which is not synchronized itself. do you synchronize access to the map in your code, at all access points? If you did not, it is possible that concurrent access to the map corrupted the internal data resulting in unpredictable behaviour.one thread has a lock, the other is trying to get it. is it possible that you have a situation where 2 locks are involved where 2 threads are waiting for the other to release the lock they need before they release the one they locked? (thread 1 locked a, waits for b + thread 2 locked b waits for a -> deadlock.)
您确定线程停止在 getEntry 处吗?该状态是可运行,所以我想它已经运行了?这一步你用jstack抓一下,就这样了。我想在 ZhouMapResourceUnit.buildTaskFinish 下有某种无限循环,并且锁永远不会被释放。
Are you sure the thread stop at getEntry ? The state is runnable, so I suppose it's run ? You catch with jstack at this step, it's all. I suppose there is sort of infinite loop under the ZhouMapResourceUnit.buildTaskFinish, and the lock is never released.
如果有多个线程,则使用 Hashtable;如果只有单个线程,则使用 HashMap。
Use Hashtable if there are multiple threads and HashMap if there is only a single thread.