我的程序被阻止了,我用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)
谢谢。答案 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。