线程死锁问题
Theads deadlock issue
环境:
Wildfly 8.1
Struts
EJB 3.1
Postgres 9
面临线程死锁问题。希望得到一些澄清。
代码:
- 一个动作 class 使用 EJB
调用两个更新
bean.writeLockedUpdate(o1) #1
...
bean.writeLockedUpdate(o1) #2
- EJB bean 的 writeLockedUpdate(Object) 通过 JPA
进行普通 JDBC 更新
场景:
- UserRequestThread1 开始并完成 #1 并在操作中做一些工作 class
- UserRequestThread2 启动并获取了 bean 上的写锁,并且在 bean.writeLockedUpdate(o1) 内。
两个用户线程都试图修改相同 o1 对象。
这两个线程的线程转储片段:
线程 1:
"default task-56" #558 prio=5 os_prio=0 tid=0x724a4400 nid=0x1674
waiting on condition [0x3d2ef000] java.lang.Thread.State:
TIMED_WAITING (parking)
at org.jboss.as.ejb3.concurrency.EJBReadWriteLock$WriteLock.tryLock(EJBReadWriteLock.java:209)
at Bean$$$view22.writeLockedUpdate(Unknown Source)
线程 2:
"default task-43" #530 prio=5 os_prio=0 tid=0x6bf10800 nid=0x15aa
runnable [0x299c8000] java.lang.Thread.State: RUNNABLE at
java.net.SocketInputStream.socketRead0(Native Method)
at org.postgresql.core.VisibleBufferedInputStream.readMore(VisibleBufferedInputStream.java:143)
at Bean$$$view22.writeLockedUpdate(Unknown Source)
可能的解释:
我相信这就是正在发生的事情。
- thread2 已获取 bean 写锁,正在等待 DB 行锁
- thread1 已获取 DB 行锁,正在等待 bean 写锁
Jconsole 没有显示任何死锁。猜测是因为被阻止的第二个锁是在数据库级别
问题:
有没有办法验证上面的解释?
提前致谢。
从 Java 和 postgresql 数据库得到确认。
线程转储清楚地显示线程 1 正在等待 EJB 写锁
对 postgres 的以下查询揭示了被阻止的操作
select bl.pid as blocked_pid, bl.mode as blocked_mode, a.usename as
blocked_user, ka.query as blocking_statement, now() - ka.query_start
as blocking_duration, kl.pid as blocking_pid, kl.mode as
blocking_mode, ka.usename as blocking_user, a.query as
blocked_statement, now() - a.query_start as blocked_duration from
pg_catalog.pg_locks bl join pg_catalog.pg_stat_activity a on bl.pid =
a.pid join pg_catalog.pg_locks kl join pg_catalog.pg_stat_activity ka
on kl.pid = ka.pid on bl.transactionid = kl.transactionid and bl.pid
!= kl.pid where not bl.granted
在我的例子中,上面的查询 returns 一行显示更新被阻止
谢谢,
拉凯什
环境:
Wildfly 8.1
Struts
EJB 3.1
Postgres 9
面临线程死锁问题。希望得到一些澄清。
代码:
- 一个动作 class 使用 EJB 调用两个更新
bean.writeLockedUpdate(o1) #1 ... bean.writeLockedUpdate(o1) #2
- EJB bean 的 writeLockedUpdate(Object) 通过 JPA 进行普通 JDBC 更新
场景:
- UserRequestThread1 开始并完成 #1 并在操作中做一些工作 class
- UserRequestThread2 启动并获取了 bean 上的写锁,并且在 bean.writeLockedUpdate(o1) 内。
两个用户线程都试图修改相同 o1 对象。
这两个线程的线程转储片段:
线程 1:
"default task-56" #558 prio=5 os_prio=0 tid=0x724a4400 nid=0x1674 waiting on condition [0x3d2ef000] java.lang.Thread.State: TIMED_WAITING (parking)
at org.jboss.as.ejb3.concurrency.EJBReadWriteLock$WriteLock.tryLock(EJBReadWriteLock.java:209)at Bean$$$view22.writeLockedUpdate(Unknown Source)
线程 2:
"default task-43" #530 prio=5 os_prio=0 tid=0x6bf10800 nid=0x15aa runnable [0x299c8000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method)
at org.postgresql.core.VisibleBufferedInputStream.readMore(VisibleBufferedInputStream.java:143)at Bean$$$view22.writeLockedUpdate(Unknown Source)
可能的解释:
我相信这就是正在发生的事情。
- thread2 已获取 bean 写锁,正在等待 DB 行锁
- thread1 已获取 DB 行锁,正在等待 bean 写锁
Jconsole 没有显示任何死锁。猜测是因为被阻止的第二个锁是在数据库级别
问题:
有没有办法验证上面的解释?
提前致谢。
从 Java 和 postgresql 数据库得到确认。
线程转储清楚地显示线程 1 正在等待 EJB 写锁
对 postgres 的以下查询揭示了被阻止的操作
select bl.pid as blocked_pid, bl.mode as blocked_mode, a.usename as blocked_user, ka.query as blocking_statement, now() - ka.query_start as blocking_duration, kl.pid as blocking_pid, kl.mode as blocking_mode, ka.usename as blocking_user, a.query as blocked_statement, now() - a.query_start as blocked_duration from pg_catalog.pg_locks bl join pg_catalog.pg_stat_activity a on bl.pid = a.pid join pg_catalog.pg_locks kl join pg_catalog.pg_stat_activity ka on kl.pid = ka.pid on bl.transactionid = kl.transactionid and bl.pid != kl.pid where not bl.granted
在我的例子中,上面的查询 returns 一行显示更新被阻止
谢谢, 拉凯什