ConcurrentHashMap死锁的疑惑
最近在使用ConcurrentHashMap的过程中,发现ConcurrentHashMap在一定的条件下会导致死锁(这个条件目前还不知道到底什么,我的ConcurrentHashMap多个线程共享,会删除和增加一些数据到ConcurrentHashMap对象里)
具体的现象是:程序跑了一段时间(10几个小时),一般2个线程会同时停下来,这时CPU占用20%左右(服务器是多CPU的),再隔一段时间又有两个线程同时停下来,这时CPU占用50%左右,这种情况一直延续知道CPU100%
起先以为程序中出现了死循环导致CPU100%,后来加了调试发现上面的现象并把其中的ConcurrentHashMap换成传统的synchronized HashMap后问题就解决了。
这个问题很奇怪,虽然现在解决了,还是不明白什么情况下会导致ConcurrentHashMap死锁呢?at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:474)
at com.tc.object.lockmanager.impl.ClientLock.waitForLock(ClientLock.java:597)
- locked <0x05cf4338> (a java.lang.Object)
at com.tc.object.lockmanager.impl.ClientLock.basicLock(ClientLock.java:212)
at com.tc.object.lockmanager.impl.ClientLock.lock(ClientLock.java:117)
at com.tc.object.lockmanager.impl.ClientLock.lock(ClientLock.java:107)
at com.tc.object.lockmanager.impl.ClientLockManagerImpl.lock(ClientLockManagerImpl.java:225)
at com.tc.object.lockmanager.impl.ThreadLockManagerImpl.lock(ThreadLockManagerImpl.java:46)
at com.tc.object.tx.ClientTransactionManagerImpl.begin(ClientTransactionManagerImpl.java:181)
at com.tc.object.bytecode.ManagerImpl.begin(ManagerImpl.java:321)
at com.tc.object.bytecode.ManagerImpl.monitorEnter(ManagerImpl.java:491)
at com.tc.object.bytecode.ManagerImpl.monitorEnter(ManagerImpl.java:479)
at com.tc.object.bytecode.ManagerUtil.monitorEnter(ManagerUtil.java:482)
at java.util.concurrent.locks.ReentrantReadWriteLock$DsoLock.lock(ReentrantReadWriteLock/java:35)
at java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.lock(ReentrantReadWriteLock/java)
at java.util.concurrent.ConcurrentHashMap$Segment.__tc_readLock(ConcurrentHashMap.java)
at java.util.concurrent.ConcurrentHashMap$Segment.get(ConcurrentHashMap.java:281)
at java.util.concurrent.ConcurrentHashMap.get(Unknown Source)
at net.deepvalue.ticket.TicketSharedData.getColumnValue(TicketSharedData.java:27)
at net.deepvalue.viewer.table.model.InBlotterTableModel$15.getValueAt(InBlotterTableModel.java:198)
at net.deepvalue.viewer.table.model.column.StringTicketColumn.getFormattedValueAt(StringTicketColumn.java:28)
at net.deepvalue.viewer.table.model.InBlotterTableModel.getValueAt(InBlotterTableModel.java:668)
at com.jidesoft.grid.DefaultTableModelWrapper.getValueAt(Unknown Source)
at com.jidesoft.grid.DefaultTableModelWrapper.getValueAt(Unknown Source)
at com.jidesoft.grid.DefaultTableModelWrapper.getValueAt(Unknown Source)
at javax.swing.JTable.getValueAt(JTable.java:1903)
at javax.swing.JTable.prepareRenderer(JTable.java:3911)
and the following is doing a putAll()
"pool-3-thread-358-In:BBR.A:IN_SIM:cl77461036-shareSlowPendingsCount" prio=6 tid=0x1fc60e70 nid=0x2318 waiting for monitor entry [0x29a9f000..0x29a9fc48]
at com.tc.object.tx.TransactionSequencer.addTransaction(TransactionSequencer.java:71)
- waiting to lock <0x05934bb0> (a com.tc.object.tx.TransactionSequencer)
at com.tc.object.tx.RemoteTransactionManagerImpl.commitInternal(RemoteTransactionManagerImpl.java:228)
at com.tc.object.tx.RemoteTransactionManagerImpl.commit(RemoteTransactionManagerImpl.java:218)
at com.tc.object.tx.ClientTransactionManagerImpl.commitInternal(ClientTransactionManagerImpl.java:430)
at com.tc.object.tx.ClientTransactionManagerImpl.commit(ClientTransactionManagerImpl.java:396)
at com.tc.object.tx.ClientTransactionManagerImpl.commit(ClientTransactionManagerImpl.java:335)
at com.tc.object.bytecode.ManagerImpl.monitorExit(ManagerImpl.java:510)
at com.tc.object.bytecode.ManagerUtil.monitorExit(ManagerUtil.java:502)
at java.util.concurrent.locks.ReentrantReadWriteLock$DsoLock.unlock(ReentrantReadWriteLock/java:58)
at java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock.unlock(ReentrantReadWriteLock/java)
at java.util.concurrent.ConcurrentHashMap$Segment.unlock(ConcurrentHashMap.java)
at java.util.concurrent.ConcurrentHashMap$Segment.put(ConcurrentHashMap.java:434)
at java.util.concurrent.ConcurrentHashMap.put(Unknown Source)
at java.util.concurrent.ConcurrentHashMap.putAll(Unknown Source)
at net.deepvalue.ticket.TicketSharedData.setColumnValues(TicketSharedData.java:69)
at net.deepvalue.ticket.DVInboundTicket.shareSlowPendingsCount(DVInboundTicket.java:365)
at net.deepvalue.ticket.DVInboundTicket$2.run(DVInboundTicket.java:383)
at net.deepvalue.masterworker.DVWorker$2.run(DVWorker.java:287)
- locked <0x0e07deb8> (a net.deepvalue.ticket.DVInboundTicket)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:417)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask/java:267)
at java.util.concurrent.FutureTask.run(FutureTask/java:54)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
at java.lang.Thread.run(Thread.java:595)
for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next)
如果在e.next=e的情况下似乎会进入死循环。
你说的这个情况还是很有可能的,这个程序写的很早了,写的人也比较多,从代码里看同一个HashMap的引用是很有可能被派发到多个线程里去的。 8 楼 puroc 2008-12-14 1.多线程使用HashMap,有死循环的问题,我遇到过两次了。
2.我现在用的也是ConcurrentHashMap,并发量很大,没遇到什么问题。 9 楼 srdrm 2009-02-26 我倒,putAll可不是太好的操作。你的设计完全是有问题的。