[jboss-user] [JBoss Cache Users] - Re: Concurrency problems - cache puts lost

a.kluge do-not-reply at jboss.com
Tue Dec 1 18:16:16 EST 2009


I extended the test a bit by adding transactions.

A minimal cache.xml:

  | <?xml version="1.0" encoding="UTF-8"?>
  | <jbosscache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  |             xmlns="urn:jboss:jbosscache-core:config:3.0">
  | 
  |    <!-- Configure the TransactionManager -->
  |    <transaction transactionManagerLookupClass="org.jboss.cache.transaction.GenericTransactionManagerLookup
  | "/>
  | 
  | </jbosscache>
  | 


  |    TransactionManager    txmanager = new DummyTransactionManagerLookup().getTransactionManager();
  | 

   Then starting and ending a transaction around the put in the write thread:

  |               for (int id=1000*iteration + 100*writer; id<1000*iteration + 100*(writer+1); id++)
  |               {
  |                     String key = "Key" + id;
  |                     txmanager.begin();
  |                     cache.put(FQN, key, VALUE);
  |                     LOG.info("Putting " + key);
  |                     Object result = cache.get(FQN, key);
  |                     if (result == null)
  |                     {
  |                       LOG.error("Missing value for immediate get of " + key + ".");
  |                     }
  |                     txmanager.commit();
  |                     result = cache.get(FQN, key);
  |                     if (result == null)
  |                     {
  |                       LOG.error("Missing value for post transaction get of " + key + ".");
  |                     }
  |               }
  | 

  This produced some interesting results:
  The immediate get never failed.
  The post commit get failed sometimes.
  The readthread get failed sometimes.
  The readthread failed on items that the post commit thread successfully returned.

For example
anonymous wrote : 
  | $ grep "post transaction" errors.20091201.log | wc -l
  | 228
  | $ grep "Missing value for Key" errors.20091201.log | wc -l
  | 3660
  | 

  Next, I synchronized a section of the write thread:


  |               for (int id=1000*iteration + 100*writer; id<1000*iteration + 100*(writer+1); id++)
  |               {
  |                     String key = "Key" + id;
  |                     synchronized (LOCK_HOLDER)
  |                     {
  |                         txmanager.begin();
  |                         cache.put(FQN, key, VALUE);
  |                         LOG.info("Putting " + key);
  |                         Object result = cache.get(FQN, key);
  |                         if (result == null)
  |                         {
  |                           LOG.error("Missing value for immediate get of " + key + ".");
  |                         }
  |                         txmanager.commit();
  |                         result = cache.get(FQN, key);
  |                         if (result == null)
  |                         {
  |                           LOG.error("Missing value for post transaction get of " + key + ".");
  |                         }
  |                     }
  |               }
  | 

  With this, I have no missed gets.

  What happens if I move the commit outside of the synchronization block?


  |               for (int id=1000*iteration + 100*writer; id<1000*iteration + 100*(writer+1); id++)
  |               {
  |                     String key = "Key" + id;
  |                     synchronized (LOCK_HOLDER)
  |                     {
  |                         txmanager.begin();
  |                         cache.put(FQN, key, VALUE);
  |                         LOG.info("Putting " + key);
  |                         Object result = cache.get(FQN, key);
  |                         if (result == null)
  |                         {
  |                           LOG.error("Missing value for immediate get of " + key + ".");
  |                         }
  |                     }
  |                     txmanager.commit();
  |                     Object result = cache.get(FQN, key);
  |                     if (result == null)
  |                     {
  |                       LOG.error("Missing value for post transaction get of " + key + ".");
  |                     }
  |               }
  | 

  Sure enough, the missing values issues return when the commit is not synchronized.

  In my production code I have placed the cache writes (puts, remove, etc) inside of
  synchronized blocks using a common lock object, and my data integrity issues
  have vanished. However, the need for the synchronization in these cases was
  definitely unexpected.

                                                                                 Alex



View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4268403#4268403

Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4268403



More information about the jboss-user mailing list