浏览 7616 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-09-23
具体的现象是:程序跑了一段时间(10几个小时),一般2个线程会同时停下来,这时CPU占用20%左右(服务器是多CPU的),再隔一段时间又有两个线程同时停下来,这时CPU占用50%左右,这种情况一直延续知道CPU100% 起先以为程序中出现了死循环导致CPU100%,后来加了调试发现上面的现象并把其中的ConcurrentHashMap换成传统的synchronized HashMap后问题就解决了。 这个问题很奇怪,虽然现在解决了,还是不明白什么情况下会导致ConcurrentHashMap死锁呢? 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-09-23
threadump出来瞧瞧了
|
|
返回顶楼 | |
发表时间:2008-09-23
补充一点,使用的JAVA版本是1.5.14
|
|
返回顶楼 | |
发表时间:2008-09-23
rainshow 写道 补充一点,使用的JAVA版本是1.5.14
已经成了过去式了,现在没办法dump了。看上有资料说ConcurrentHashMap在putAll的时候产生了deadlock,我把他的那个情况贴一下 "AWT-EventQueue-0" prio=6 tid=0x1044bba0 nid=0x2d80 in Object.wait() [0x12bbd000..0x12bbfcc8] 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) |
|
返回顶楼 | |
发表时间:2008-09-23
更正一下,并且说详细一点(附件中是对象关系图)
我们的一个系统,以下简称V系统 1)V系统包含2、3个Producer线程他们往队列里放入一个Map对象(HashMap)。但是这套程序存在一些问题,不排除不同的Map对象里还有对相同的对象的引用,也就是说map1和map2可能都引用了someObj,也有可能引用了一些共享数据 2)V系统同时包含50-100个Consumer线程,他们从队列里取出Map对象map3,并在取出后建立自己的对象map4,并把map3中的引用putAll到map4中 3)这些Producer线程和Consumer线程共享了一些配置数据(这些数据都是存放在ConcurrentHashMap中) 问题出现在把map3中的引用putAll到map4中的时候引起了死锁 关于程序设计的问题我们这里不讨论,这里会导致死锁的有两个地方,Queue和ConcurrentHashMap,但他们本身也不会死锁,我比较疑惑的是究竟在什么情形下会导致程序死锁。再次强调一下,在这里除了Queue和共享数据外,其他的map都是HashMap,putAll时的死锁有点匪夷所思。 当然大家也不要被我的想法给限制了,也有可能不是死锁,反正现象就是2个线程停在putAll哪里不动了,狂吃CPU Queue这个类的源代码如下: public class Queue { private final int maxSize;//如果超过最大值则删除 private volatile LinkedList<Object> queue = new LinkedList<Object>(); private Lock lock; private Condition notEmpty; public Queue(int maxSize) { this.maxSize = maxSize > 0 ? maxSize : Integer.MAX_VALUE; lock = new ReentrantLock(); notEmpty = lock.newCondition(); } public void put(Object v) { lock.lock(); try { int s = queue.size(); if (s > this.maxSize) { queue.removeLast(); } queue.addFirst(v); notEmpty.signal(); } finally { lock.unlock(); } } public int size() { return queue.size(); } public Object get() { return get(-1); } public Object get(long timeout) { lock.lock(); try { Object obj = null; for (int tryCount = 0; obj == null && tryCount < 100; tryCount++) { if (queue.isEmpty()) { if (timeout > 0) { notEmpty.await(timeout, TimeUnit.MILLISECONDS); return readOne(); } else { notEmpty.await(); } } obj = readOne(); } return obj; } catch (InterruptedException e) { return null; } finally { lock.unlock(); } } private Object readOne() { if (!queue.isEmpty()) { return queue.removeLast(); } else { return null; } } public boolean isEmpty() { return queue.isEmpty(); } } |
|
返回顶楼 | |
发表时间:2008-09-23
ConcurrentHashMap用的是似有锁,用户拿不到锁对象,怎么会死锁阿
|
|
返回顶楼 | |
发表时间:2008-09-24
cpu占用那么多,说明是死循环,比如HashMap在多线程下,get操作有可能陷入死循环,注意这种要求同步的访问。
|
|
返回顶楼 | |
发表时间:2008-09-24
nihongye 写道 cpu占用那么多,说明是死循环,比如HashMap在多线程下,get操作有可能陷入死循环,注意这种要求同步的访问。
这个说法可靠吗?我看了一下HashMap的get方法源码 for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) 如果在e.next=e的情况下似乎会进入死循环。 你说的这个情况还是很有可能的,这个程序写的很早了,写的人也比较多,从代码里看同一个HashMap的引用是很有可能被派发到多个线程里去的。 |
|
返回顶楼 | |
发表时间:2008-12-14
1.多线程使用HashMap,有死循环的问题,我遇到过两次了。
2.我现在用的也是ConcurrentHashMap,并发量很大,没遇到什么问题。 |
|
返回顶楼 | |
发表时间:2009-02-26
我倒,putAll可不是太好的操作。你的设计完全是有问题的。
|
|
返回顶楼 | |