1 2 Previous Next 24 Replies Latest reply on Jun 2, 2005 10:52 AM by adrian.brock Go to original post
      • 15. Re: mt-issues with org.jboss.tm.TransactionLocal
        bill.burke

        lock()/unlock() should not be used internally in the TransactionLocal implementation as locking is not needed.

        TransactionLocal does need to provide a lock()/unlock() function so that you can protect the transaction local for multi-threaded transaction access within your code. Like, if in your application code, you need to check and set the tx local. If get() == null then set. You'll want to local.lock() if (get() == null) then set local.unlock().

        • 16. Re: mt-issues with org.jboss.tm.TransactionLocal
          dimitris

          Ok, lock()/unlock() similar to TransactionImpl was added, along with a helper SynchronizedTransactionLocal class (in the branch I'm working).

          Thanks

          • 17. Re: mt-issues with org.jboss.tm.TransactionLocal
            dimitris

            Actually the locking needs to be smarter than the one in TransactionImp because we want to "lock" the ThreadLocal based on the active transaction, i.e. synchronize the threads inside the same tx only.

            My implementation is a bit naive for the time being, due to the notifyAll().

            I guess I need to look for an EDU.oswego equivalent.

            ...
             /**
             * Set to monitor which transactions are "locked"
             * with lock() and unlock().
             */
             private static final Set txLockSet = new HashSet();
            ...
             /**
             * Lock using the current transaction
             */
             public void lock()
             {
             lock(getTransaction());
             }
            
             /**
             * Lock using the provided transaction
             *
             * @param transaction
             */
             public void lock(Transaction transaction)
             {
             if (transaction == null)
             {
             throw new IllegalStateException("there is no transaction");
             }
            
             synchronized (txLockSet)
             {
             while (!txLockSet.add(transaction))
             {
             try
             {
             txLockSet.wait();
             }
             catch (InterruptedException ex)
             {
             // ignore
             }
             }
             // got the lock
             }
             }
            
             /**
             * Unlock using the current transaction
             */
             public void unlock()
             {
             unlock(getTransaction());
             }
            
             public void unlock(Transaction transaction)
             {
             if (transaction == null)
             {
             throw new IllegalStateException("there is no transaction");
             }
            
             synchronized (txLockSet)
             {
             if (!txLockSet.remove(transaction))
             {
             throw new IllegalStateException("Unlocking, but not locked");
             }
             // REVISE
             txLockSet.notifyAll();
             }
             }
            


            • 18. Re: mt-issues with org.jboss.tm.TransactionLocal
              dimitris

              Another thing, txLockSet shouldn't be static, since we protect the state of each particular TreadLocal per tx.

              • 19. Re: mt-issues with org.jboss.tm.TransactionLocal

                ReentrantLock.


                You don't want to ignore/eat InterruptedException.
                It is thrown for a reason.

                I hate the early java examples where people didn't know what to do with InterruptedException and just ignored it.

                If you want to continue through the InterruptedException you should restore
                the state of the thread to interrupted.

                 boolean interrupted = false;
                 synchronized (txLockSet)
                 {
                 while (!txLockSet.add(transaction))
                 {
                 try
                 {
                 txLockSet.wait();
                 }
                 catch (InterruptedException ex)
                 {
                 interrupted = true;
                 }
                 }
                 if (interrupted)
                 Thread.interrupt();
                 // got the lock
                 }
                 }
                


                • 20. Re: mt-issues with org.jboss.tm.TransactionLocal

                  Also, the current TransactionLocal.get() allows a null transaction (returning null).
                  So should interpret the lock()/unlock() as noops when there is no transaction.

                  • 21. Re: mt-issues with org.jboss.tm.TransactionLocal

                     

                    "dimitris@jboss.org" wrote:
                    Another thing, txLockSet shouldn't be static, since we protect the state of each particular TreadLocal per tx.


                    Correct. NO GLOBAL LOCKS. It is transaction + object (threadlocal).

                    You might also consider adding a timeout to the lock such that we don't wait
                    forever. e.g. if you are waiting 5 minutes to get access to the thread local
                    it is almost certainly a deadlock.

                    • 22. Re: mt-issues with org.jboss.tm.TransactionLocal
                      dimitris

                      Thanks a lot for the hints!

                      Actually we make the same mistake in TransactionImpl :)

                      ...
                       try
                       {
                       // Wakeup happens when:
                       // - notify() is called from unlock()
                       // - notifyAll is called from instanceDone()
                       wait();
                       }
                       catch (InterruptedException ex)
                       {
                       // ignore
                       }
                      ...
                      


                      • 23. Re: mt-issues with org.jboss.tm.TransactionLocal

                         

                        "dimitris@jboss.org" wrote:

                        My implementation is a bit naive for the time being, due to the notifyAll().


                        notify leaves it to the underlying lock implementation to decide which thread gets
                        woken (e.g. this might implement fair queuing)
                        notifyAll wakes up all the threads and leaves it to a race in the OS scheduler as to
                        who aquires the lock.

                        Semantically they should be same in this circumstance, with notify being more efficient.

                        • 24. Re: mt-issues with org.jboss.tm.TransactionLocal

                           

                          "dimitris@jboss.org" wrote:
                          Thanks a lot for the hints!

                          Actually we make the same mistake in TransactionImpl :)


                          Then fix it :-)
                          Or at least report it on JIRA if you don't have time to analyse/test the consequences.


                          1 2 Previous Next