今天线上的tomcat线程全部被吃完,通过jstack查看线程信息,发现有很多线程在等待锁对象,有大量的线程卡在ConnectionPoolImpl的484行,而且都是在 waiting to lock <0x0000000780fd06f8>,如下:"http-bio-8118-exec-1" daemon prio=10 tid=0x00007fbd68001800 nid=0xb78 waiting for monitor entry [0x00007fbe66140000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.seasar.extension.dbcp.impl.ConnectionPoolImpl.checkInTx(ConnectionPoolImpl.java:484)
- waiting to lock <0x0000000780fd06f8> (a org.seasar.extension.dbcp.impl.ConnectionPoolImpl)
at org.seasar.extension.dbcp.impl.ConnectionWrapperImpl.close(ConnectionWrapperImpl.java:283)
at org.seasar.extension.jdbc.manager.JdbcContextImpl.destroy(JdbcContextImpl.java:104)
…………ConnectionPoolImpl的484行代码如下
然后查看到底是哪个线程获得了0x0000000780fd06f8这个锁对象,发现了如下一个线程:"http-bio-8118-exec-3" daemon prio=10 tid=0x00007fbd68004800 nid=0xb7a waiting for monitor entry [0x00007fbe65f3e000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.seasar.extension.dbcp.impl.ConnectionPoolImpl.checkInTx(ConnectionPoolImpl.java:484)
- locked <0x00000007864498a8> (a org.seasar.extension.dbcp.impl.ConnectionPoolImpl)
at org.seasar.extension.dbcp.impl.ConnectionWrapperImpl.close(ConnectionWrapperImpl.java:283)
at org.seasar.extension.jdbc.manager.JdbcContextImpl.destroy(JdbcContextImpl.java:104)
…………问题来了,既然这个线程获得了0x00000007864498a8这个锁对象并加锁了,为什么还BLOCKED在ConnectionPoolImpl.java:484行呢?,既然线程是BLOCKED,那他又是在等待哪个锁对象呢?(等待锁对象时,不是线程信息里面都会有waiting to lock <0x...........>信息吗?),请大神指教和交流~ps:间隔一段时间后再运行jstack命令,http-bio-8118-exec-3线程的状态一直都没变过为了验证我的想法,写了一个测试程序,运行后,使用jsatck查看线程信息:
main方法:public static void main(String[] args) throws Exception {
Lock l = new Lock();
new TestThread(l).start();new TestThread(l).start();
new TestThread(l).start();new TestThread(l).start();
new TestThread(l).start(); new TestThread(l).start();
}
}Class:Lockpublic class Lock{
public synchronized void test(){
System.out.println("in"+Thread.currentThread().getName());
try { Thread.sleep(260000L); } catch (InterruptedException e) { }
}
}Class:TestThread :class TestThread extends Thread{
Lock lock;
public TestThread(Lock lock){
this.lock = lock;
}
@Override
public void run() {
lock.test();
}
}然后是jstack命令返回的线程信息:其中1号线程获取了Lock的锁对象,然后进入Sleep,线程变为TIMED_WAITING状态,其他线程都在等待Lock对象,0x23a568a0;通过查看dump下来的内存,0x23a568a0这个对象正是在main方法里面new出来的那个lock
java.lang.Thread.State: BLOCKED (on object monitor)
at org.seasar.extension.dbcp.impl.ConnectionPoolImpl.checkInTx(ConnectionPoolImpl.java:484)
- waiting to lock <0x0000000780fd06f8> (a org.seasar.extension.dbcp.impl.ConnectionPoolImpl)
at org.seasar.extension.dbcp.impl.ConnectionWrapperImpl.close(ConnectionWrapperImpl.java:283)
at org.seasar.extension.jdbc.manager.JdbcContextImpl.destroy(JdbcContextImpl.java:104)
…………ConnectionPoolImpl的484行代码如下
然后查看到底是哪个线程获得了0x0000000780fd06f8这个锁对象,发现了如下一个线程:"http-bio-8118-exec-3" daemon prio=10 tid=0x00007fbd68004800 nid=0xb7a waiting for monitor entry [0x00007fbe65f3e000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.seasar.extension.dbcp.impl.ConnectionPoolImpl.checkInTx(ConnectionPoolImpl.java:484)
- locked <0x00000007864498a8> (a org.seasar.extension.dbcp.impl.ConnectionPoolImpl)
at org.seasar.extension.dbcp.impl.ConnectionWrapperImpl.close(ConnectionWrapperImpl.java:283)
at org.seasar.extension.jdbc.manager.JdbcContextImpl.destroy(JdbcContextImpl.java:104)
…………问题来了,既然这个线程获得了0x00000007864498a8这个锁对象并加锁了,为什么还BLOCKED在ConnectionPoolImpl.java:484行呢?,既然线程是BLOCKED,那他又是在等待哪个锁对象呢?(等待锁对象时,不是线程信息里面都会有waiting to lock <0x...........>信息吗?),请大神指教和交流~ps:间隔一段时间后再运行jstack命令,http-bio-8118-exec-3线程的状态一直都没变过为了验证我的想法,写了一个测试程序,运行后,使用jsatck查看线程信息:
main方法:public static void main(String[] args) throws Exception {
Lock l = new Lock();
new TestThread(l).start();new TestThread(l).start();
new TestThread(l).start();new TestThread(l).start();
new TestThread(l).start(); new TestThread(l).start();
}
}Class:Lockpublic class Lock{
public synchronized void test(){
System.out.println("in"+Thread.currentThread().getName());
try { Thread.sleep(260000L); } catch (InterruptedException e) { }
}
}Class:TestThread :class TestThread extends Thread{
Lock lock;
public TestThread(Lock lock){
this.lock = lock;
}
@Override
public void run() {
lock.test();
}
}然后是jstack命令返回的线程信息:其中1号线程获取了Lock的锁对象,然后进入Sleep,线程变为TIMED_WAITING状态,其他线程都在等待Lock对象,0x23a568a0;通过查看dump下来的内存,0x23a568a0这个对象正是在main方法里面new出来的那个lock
ConnectionPoolImpl 里面也没有其他同步方法了。
连接池开的40个;主要在意的是为什么那个线程获得锁对象了,线程还是BLOCK状态,而且也没显示等待哪个对象。所以没太关注连接池情况,得等明天再重现了这个问题看看;
是的,就因为sleep不释放锁,所以我写个测试让一个线程一直拥有所,其他线程被阻塞时,通过jstack命令查看线程信息是什么情况,事实来看,被阻塞的线程情况跟线上项目的线程情况一样,都是在waiting to lock xxxx对象,而获得锁的那个线程是locked xxx对象。
ConnectionPoolImpl 里面也没有其他同步方法了。
连接池开的40个;主要在意的是为什么那个线程获得锁对象了,线程还是BLOCK状态,而且也没显示等待哪个对象。所以没太关注连接池情况,得等明天再重现了这个问题看看;
我网上找了个类似的源代码看看,好几个同步方法呢。
哦,失误了,应该是截错图了。当时确实有很多线程在等待0x00000007864498a8这个对象。待会再上个图。那还如直接把所有的 stack都贴上来呢。