I'm not sure whether it is problem of cache, hibernate or my design. Please give me an advise if there's a well-known pattern to solve this.
Suppose I have an entity with two props - key and value mapped to a table with two fields. | <hibernate-mapping> | <class name="test.TestEntity" table="TEST_ENTITY"> | <cache usage="transactional"/> | | <id name="id" type="int" > | <generator class="assigned"/> | </id> | | <property name="value" type="int"/> | </class> | </hibernate-mapping> | | Suppose I have a servlet which prints values for keys passed as parameter. (like /servletName?keyList=1,2,3,4) Servlet looks like | void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | | StringTokenizer st = new StringTokenizer(request.getParameter("keyList"), ","); | UserTransaction utx; | try { | utx = (UserTransaction)new InitialContext().lookup("UserTransaction"); | utx.begin(); | | Session session = HibernateContext.getSession("java:/hibernate/SessionFactory"); | | while(st.hasMoreTokens()){ | Integer id = new Integer(st.nextToken()); | | System.out.println(""+Thread.currentThread()+" loading "+id); | session.load(TestEntity.class, id); | Thread.sleep(1000); | } | | utx.commit(); | } catch (Exception e) { | e.printStackTrace(); | } | | | | } | | If I request simultaneously following url's: ..../servletName?keyList=1,2,3,4,5,6,7,8,9,10 and ..../servletName?keyList=10,9,8,7,6,5,4,3,2,1 I hava 100% chance to get a deadlock. anonymous wrote : | 20:06:29,588 INFO [STDOUT] Thread[http-0.0.0.0-8180-Processor25,5,jboss] loading 1 | 20:06:31,635 INFO [STDOUT] Thread[http-0.0.0.0-8180-Processor24,5,jboss] loading 10 | 20:06:37,807 INFO [STDOUT] Thread[http-0.0.0.0-8180-Processor25,5,jboss] loading 2 | 20:06:39,041 INFO [STDOUT] Thread[http-0.0.0.0-8180-Processor25,5,jboss] loading 3 | 20:06:40,197 INFO [STDOUT] Thread[http-0.0.0.0-8180-Processor25,5,jboss] loading 4 | 20:06:41,619 INFO [STDOUT] Thread[http-0.0.0.0-8180-Processor25,5,jboss] loading 5 | 20:06:42,760 INFO [STDOUT] Thread[http-0.0.0.0-8180-Processor25,5,jboss] loading 6 | 20:06:43,057 INFO [STDOUT] Thread[http-0.0.0.0-8180-Processor24,5,jboss] loading 9 | 20:06:43,901 INFO [STDOUT] Thread[http-0.0.0.0-8180-Processor25,5,jboss] loading 7 | 20:06:44,229 INFO [STDOUT] Thread[http-0.0.0.0-8180-Processor24,5,jboss] loading 8 | 20:06:45,119 INFO [STDOUT] Thread[http-0.0.0.0-8180-Processor25,5,jboss] loading 8 | 20:06:45,401 INFO [STDOUT] Thread[http-0.0.0.0-8180-Processor24,5,jboss] loading 7 | 20:07:00,135 ERROR [IdentityLock] read lock for //hibernate/test/TestEntity/8 could not be acquired after 15000 ms. Lock | map ownership Read lock owners: [] | Write lock owner: :2 | (caller=:1) | 20:07:00,166 INFO [STDOUT] net.sf.hibernate.cache.CacheException: org.jboss.cache.lock.TimeoutException: lock for //hibe | rnate/test/TestEntity/8 could not be acquired after 15000ms. Lock map ownership Read lock owners: [] | Write lock owner: :2 | | at net.sf.hibernate.cache.TreeCache.get(TreeCache.java:61) | at net.sf.hibernate.cache.TransactionalCache.get(TransactionalCache.java:29) | at net.sf.hibernate.impl.SessionImpl.doLoad(SessionImpl.java:2121) | at net.sf.hibernate.impl.SessionImpl.doLoadByClass(SessionImpl.java:2000) | at net.sf.hibernate.impl.SessionImpl.load(SessionImpl.java:1929) | at test.TestCacheLockServlet.service(TestCacheLockServlet.java:57) | at javax.servlet.http.HttpServlet.service(HttpServlet.java:810) | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237) | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157) | at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:75) | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:186) | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157) | at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:214) | at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104) | at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520) | at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:198) | at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:152) | at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104) | at org.jboss.web.tomcat.security.CustomPrincipalValve.invoke(CustomPrincipalValve.java:66) | at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102) | at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:162) | at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102) | at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520) | at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137) | at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104) | at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:118) | at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102) | at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:535) | at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102) | at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520) | at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) | at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104) | at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520) | at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929) | at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160) | at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:799) | at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:705) | at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:577) | at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683) | at java.lang.Thread.run(Thread.java:595) | Caused by: org.jboss.cache.lock.TimeoutException: lock for //hibernate/test/TestEntity/8 could not be acquired after 1500 | 0ms. Lock map ownership Read lock owners: [] | Write lock owner: :2 | | at org.jboss.cache.lock.IdentityLock.acquireReadLock(IdentityLock.java:218) | at org.jboss.cache.Node.acquireReadLock(Node.java:418) | at org.jboss.cache.Node.acquire(Node.java:399) | at org.jboss.cache.interceptors.LockInterceptor.lock(LockInterceptor.java:202) | at org.jboss.cache.interceptors.LockInterceptor.invoke(LockInterceptor.java:144) | at org.jboss.cache.interceptors.Interceptor.invoke(Interceptor.java:40) | at org.jboss.cache.interceptors.CreateIfNotExistsInterceptor.invoke(CreateIfNotExistsInterceptor.java:50) | at org.jboss.cache.interceptors.Interceptor.invoke(Interceptor.java:40) | at org.jboss.cache.interceptors.UnlockInterceptor.invoke(UnlockInterceptor.java:35) | at org.jboss.cache.TreeCache.invokeMethod(TreeCache.java:2978) | at org.jboss.cache.TreeCache.get(TreeCache.java:1509) | at org.jboss.cache.TreeCache.get(TreeCache.java:1493) | at net.sf.hibernate.cache.TreeCache.get(TreeCache.java:58) | ... 39 more | 20:07:00,401 ERROR [IdentityLock] read lock for //hibernate/test/TestEntity/7 could not be acquired after 15000 ms. Lock | map ownership Read lock owners: [] | Write lock owner: :1 | (caller=:2) | 20:07:00,416 INFO [STDOUT] net.sf.hibernate.cache.CacheException: org.jboss.cache.lock.TimeoutException: lock for //hibe | rnate/test/TestEntity/7 could not be acquired after 15000ms. Lock map ownership Read lock owners: [] | Write lock owner: :1 | | at net.sf.hibernate.cache.TreeCache.get(TreeCache.java:61) | at net.sf.hibernate.cache.TransactionalCache.get(TransactionalCache.java:29) | at net.sf.hibernate.impl.SessionImpl.doLoad(SessionImpl.java:2121) | at net.sf.hibernate.impl.SessionImpl.doLoadByClass(SessionImpl.java:2000) | at net.sf.hibernate.impl.SessionImpl.load(SessionImpl.java:1929) | at test.TestCacheLockServlet.service(TestCacheLockServlet.java:57) | at javax.servlet.http.HttpServlet.service(HttpServlet.java:810) | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237) | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157) | at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:75) | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:186) | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157) | at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:214) | at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104) | at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520) | at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:198) | at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:152) | at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104) | at org.jboss.web.tomcat.security.CustomPrincipalValve.invoke(CustomPrincipalValve.java:66) | at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102) | at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:162) | at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102) | at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520) | at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137) | at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104) | at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:118) | at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102) | at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:535) | at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102) | at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520) | at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) | at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104) | at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520) | at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929) | at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160) | at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:799) | at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:705) | at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:577) | at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683) | at java.lang.Thread.run(Thread.java:595) | Caused by: org.jboss.cache.lock.TimeoutException: lock for //hibernate/test/TestEntity/7 could not be acquired after 1500 | 0ms. Lock map ownership Read lock owners: [] | Write lock owner: :1 | | at org.jboss.cache.lock.IdentityLock.acquireReadLock(IdentityLock.java:218) | at org.jboss.cache.Node.acquireReadLock(Node.java:418) | at org.jboss.cache.Node.acquire(Node.java:399) | at org.jboss.cache.interceptors.LockInterceptor.lock(LockInterceptor.java:202) | at org.jboss.cache.interceptors.LockInterceptor.invoke(LockInterceptor.java:144) | at org.jboss.cache.interceptors.Interceptor.invoke(Interceptor.java:40) | at org.jboss.cache.interceptors.CreateIfNotExistsInterceptor.invoke(CreateIfNotExistsInterceptor.java:50) | at org.jboss.cache.interceptors.Interceptor.invoke(Interceptor.java:40) | at org.jboss.cache.interceptors.UnlockInterceptor.invoke(UnlockInterceptor.java:35) | at org.jboss.cache.TreeCache.invokeMethod(TreeCache.java:2978) | at org.jboss.cache.TreeCache.get(TreeCache.java:1509) | at org.jboss.cache.TreeCache.get(TreeCache.java:1493) | at net.sf.hibernate.cache.TreeCache.get(TreeCache.java:58) | ... 39 more | | The thing is: when I try to read an entity which is missing in cache it is loaded from storage and get written to cache leaving a write lock. As soon as entities get evicted from cache, ANY "read" of entity can become "write" to cache requiring write lock. My question is: is it possible to avoid deadlocks when reading entities in random order (very common scenario). View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=3863790#3863790 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=3863790 ------------------------------------------------------- This SF.Net email is sponsored by: IntelliVIEW -- Interactive Reporting Tool for open source databases. Create drag-&-drop reports. Save time by over 75%! Publish reports on the web. Export to DOC, XLS, RTF, etc. Download a FREE copy at http://www.intelliview.com/go/osdn_nl _______________________________________________ JBoss-Development mailing list JBoss-Development@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jboss-development