почему java.util.HashMap.getEntry может заблокировать мою программу?

моя программа была заблокирована, я использовал jstack commander для анализа, следующий поток взял блокировку «0x0000000603f02ae0», а другие потоки не смогли получить блокировку.
Я ждал по крайней мере один час, но поток не сделал ' t unlock, мой вопрос в том, почему состояние потока RUNNING и останавливается на java.util.HashMap.getEntry (HashMap.java:347)? это ошибка JDK оракула (солнца)?

моя версия jdk:
версия java "1.6.0_21"
Среда выполнения Java (TM) SE (сборка 1.6.0_21-b06)
64-разрядная серверная виртуальная машина Java HotSpot (TM) (сборка 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 ) по адресу java.util.HashMap.containsKey (HashMap.java:335) по адресу com.youlongqingfeng.pandora.context.ArmiesContext._getArmy (ArmiesContext.java:239) по адресу com.youlongqingfeng.pandora.context.ArmiesBank. java: 169) на com.youlongqingfeng.pandora.model.City.getTotalApplianceMap (City.java:4519) на com.youlongqingfeng.pandora.model.City.calculateMemoryResource (City.java:4636) на com.youlongqing.feng.p .City.buildTaskFinish (City.java:1089) на com.youlongqingfeng.pandora.map.unit.ZhouMapResourceUnit.buildTaskFinish (ZhouMapResourceUnit.java:1618) - заблокировано ‹0x0000000603f02aengyoulong (a com.youlongqingfeng.pandora.map.unit.ZhouMapResourceUnit.buildTaskFinish (ZhouMapResourceUnit.java:1618) - заблокировано ‹0x0000000603f02aengyoulong (a com. pandora.map.unit.ZhouMapResourceUnit) по адресу com.youlongqingfeng.pandora.trigger.BuildTrigger.innerRun (BuildT rigger.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: ЗАБЛОКИРОВАНО (на мониторе объекта) в com.youlongqingfeng.pandora.map.Runit.ZhouMap. armiesGroupReturnBack (ZhouMapResourceUnit.java:2279) - ожидание блокировки ‹0x0000000603f02ae0> (com.youlongqingfeng.pandora.map.unit.ZhouMapResourceUnit) в com.youlongqingfeng.gerpandora.TriggerGroupArmy .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 $ ScheduledExduledFutureTask.accessThread $ 301 ( ) в java.util.concurrent.ScheduledT hreadPoolExecutor $ ScheduledFutureTask.run (ScheduledThreadPoolExecutor.java:207) в java.util.concurrent.ThreadPoolExecutor $ Worker.runTask (ThreadPoolExecutor.java:886) в java.util.ThreadPoolExecutor. в java.lang.Thread.run (Thread.java:619)

Спасибо.


person Peter Lee    schedule 07.08.2010    source источник
comment
Какие другие потоки работают одновременно - в частности, есть ли другой поток, обращающийся к тому же ресурсу?   -  person Will A    schedule 07.08.2010


Ответы (4)


Фактически, вы могли использовать ConcurrentHashMap вместо HashMap. HashMap перейдет в состояние блокировки, когда разные потоки будут обращаться к карте в цикле или в чем-то подобном. ConcurrentHashMap можно эффективно использовать. Он синхронизирован и эффективен. Он не блокирует всю карту, он просто блокирует текущий сегмент, к которому осуществляется доступ.

person aNish    schedule 08.08.2010

Некоторые моменты, которые следует учитывать:

  • вы используете HashMap, который сам не синхронизируется. вы синхронизируете доступ к карте в вашем коде на всех точках доступа? Если вы этого не сделали, возможно, что одновременный доступ к карте повредил внутренние данные, что привело к непредсказуемому поведению.

  • один поток имеет блокировку, другой пытается ее получить. Возможно ли, что у вас есть ситуация, когда задействованы 2 блокировки, когда 2 потока ждут, пока другой освободит нужную им блокировку, прежде чем они освободят тот, который они заблокировали? (поток 1 заблокирован a, ждет b + поток 2 заблокирован b ждет a -> тупик.)

person rsp    schedule 07.08.2010
comment
спасибо, я получил ответ, потому что поток получил ReadLock, но я записал некоторые данные в карту, поэтому возникла ошибка. - person Peter Lee; 07.08.2010
comment
Я обнаружил ту же ошибку в mybatis ~ getEntry просто зацикливался навсегда. Так грустно - person wener; 18.10.2014
comment
@PeterLee Привет, у меня очень похожая ситуация в PROD с HashMap, доступ к которой осуществляется в многопоточном процессе, когда все 5 потоков блокируются at java.util.HashMap.getEntry(HashMap.java:480). Я хочу понять ваше заявление о ReadLock. Вы имеете в виду, что вы просто put просматривали элементы в HashMap в то время, когда элементы были прочитаны? или у вас была реализация в вашем коде ReadWriteLock.readLock() для получения элементов с карты, и ничего не было сделано для put вставки элемента? - person vadimbog; 30.05.2015

Вы уверены, что поток останавливается на getEntry? Состояние готово, так что, я полагаю, оно запущено? На этом шаге ловишь с jstack, вот и все. Я полагаю, что в ZhouMapResourceUnit.buildTaskFinish существует своего рода бесконечный цикл, и блокировка никогда не снимается.

person Istao    schedule 07.08.2010

Используйте Hashtable, если есть несколько потоков, и HashMap, если есть только один поток.

person khairil    schedule 07.08.2010
comment
Hashtable работает медленно, я использую readWriteLock, чтобы решить эту проблему, спасибо. - person Peter Lee; 07.08.2010