[concurrency-interest] Nested synchronized

David Holmes davidcholmes at aapt.net.au
Thu Jan 5 21:33:48 EST 2012


If you have a hang from which you can't get a stack dump it generally
indicates that the VM can't reach a safepoint. At that point you need a
native tools (eg pstack on Solaris) or a debugger to help you see the
stacks.

The inability to reach a safepoint indicates to me that there is a livelock,
probably involving spinning on locks (hence why -UseSpinning can avoid the
problem). Can you confirm that CPU is being consumed during the "hang"?

Anyway it's a VM bug.

David
  -----Original Message-----
  From: Howard Lovatt [mailto:howard.lovatt at gmail.com]
  Sent: Friday, 6 January 2012 12:28 PM
  To: Vitaly Davidovich
  Cc: dholmes at ieee.org; concurrency-interest at cs.oswego.edu
  Subject: Re: [concurrency-interest] Nested synchronized


  Hi,


  No luck with -XX:-EliminateLocks, still hangs. Also I can't get a stack
dump from kill. Tried kill -1 to kill -9, no luck. Will try reentrant locks
and report.


  Thanks for all the suggestions,


   -- Howard.


  On 6 January 2012 13:01, Vitaly Davidovich <vitalyd at gmail.com> wrote:

    Sorry left another bit out.  Since the suspicion is the nesting
try -XX:-EliminateLocks, IIRC.  Get rid of the other flags too so we're
controlling one thing at a time.

    On Jan 5, 2012 8:55 PM, "Vitaly Davidovich" <vitalyd at gmail.com> wrote:

      Possible but would be good to have call stacks.  Also can you try
using a reentrant lock instead of synchronized?

      On Jan 5, 2012 8:44 PM, "Howard Lovatt" <howard.lovatt at gmail.com>
wrote:

        Hi Vitaly,


        If I add the following JVM
options, -ea -XX:+UseBiasedLocking -XX:-UseSpinning -XX:+UseTLAB -XX:+UseThr
eadPriorities, then the program runs. Indicating to me that it is a JVM
problem.


         -- Howard.


        On 6 January 2012 12:18, Vitaly Davidovich <vitalyd at gmail.com>
wrote:

          Howard,

          Have you captured call stacks when it hangs?

          Vitaly

          On Jan 5, 2012 8:14 PM, "Howard Lovatt" <howard.lovatt at gmail.com>
wrote:

            Hi David,


            There is only one sum object shared between the two threads (1st
line of main) and hence all synchronization is on the same object. Therefore
I think the code should work (even though the second synchronization is
redundant). As a double check on my understanding I just added a specific
mutex object to the code and synchronized on that and got the same result.


            Have I understood you comment correctly?


            Thanks,


             -- Howard.


            On 6 January 2012 12:00, David Holmes <davidcholmes at aapt.net.au>
wrote:

              That's not nested synchronization as you are using two
different objects. It is a classic deadlock:

              - sync method on Obj A calls sync method on Obj B
              - sync method on Obj B calls sync method on Objj A

              Thread 1 does the call to ObjA
              Thread 2 does the call to Obj B

              David
              ------
                -----Original Message-----
                From: concurrency-interest-bounces at cs.oswego.edu
[mailto:concurrency-interest-bounces at cs.oswego.edu]On Behalf Of Howard
Lovatt
                Sent: Friday, 6 January 2012 10:53 AM
                To: concurrency-interest at cs.oswego.edu
                Subject: [concurrency-interest] Nested synchronized


                Hi,


                I have seen something I think is a JVM bug but would like to
check my understanding before reporting a problem. The following program
normally hangs, i.e. the problem is intermittent, on my computer, MacBook
Pro, Java 6 or 7, 4 core processor. The problem is that there are
synchronized methods, isSetA1 and isSetA2 (near end of listing below), that
call another synchronized method, conditionallySumArguments (at end of
listing below). The second synchronized is unnecessary since the method is
always called within an already synchronized method and if the second
synchronized is removed the program works as expected. However I think an
extra synchronized should be redundant, not a problem?


                  package nestedsynchronizedproblem;


                  import java.util.concurrent.Callable;
                  import java.util.concurrent.ExecutorService;
                  import java.util.concurrent.Executors;
                  import java.util.concurrent.TimeUnit;


                  import static java.lang.System.*;


                  /**
                   * Test of nested synchronized. Mimics calling a parallel
sum method.
                   *
                   * @author  Howard Lovatt
                   */
                  public class NestedSynchronizedProblem {
                    private static final int loops = 10 * 1000 * 1000; //
This needs to be large for hanging!


                    public static void main( final String... notUsed )
throws InterruptedException {
                      final ParrallelSumMethod sum = new
ParrallelSumMethod();
                      final Callable<Void> setA1 = new Callable<Void>() {
                        @Override public Void call() throws Exception {
                          for ( int l = 0; l < loops; l++ ) { sum.setA1(
l ); }
                          return null;
                        }
                      };
                      final Callable<Void> setA2 = new Callable<Void>() {
                        @Override public Void call() throws Exception {
                          for ( int l = 0; l < loops; l++ ) { sum.setA2(
l ); }
                          return null;
                        }
                      };
                      final ExecutorService pool =
Executors.newCachedThreadPool();
                      pool.submit( setA1 );
                      pool.submit( setA2 );
                      pool.shutdown();
                      final boolean ok = pool.awaitTermination( 1,
TimeUnit.MINUTES );
                      out.println( sum.getSum() + (ok ? ", terminated ok" :
", failed to terminate") );
                      pool.shutdownNow();
                    }
                  }




                  final class ParrallelSumMethod {
                    private long sum = 0;
                    private Long a1 = null;
                    private Long a2 = null;


                    public void setA1( final long a1Arg ) throws
InterruptedException {
                      for ( ;; ) {
                        if ( isSetA1( a1Arg ) ) { return; }
                        checkForInterrupt();
                      }
                    }


                    public void setA2( final long a2Arg ) throws
InterruptedException {
                      for ( ;; ) {
                        if ( isSetA2( a2Arg ) ) { return; }
                        checkForInterrupt();
                      }
                    }


                    public Long getSum() { return sum; }


                    private static void checkForInterrupt() throws
InterruptedException {
                      if ( Thread.interrupted() ) { throw new
InterruptedException(); }
                    }


                    private synchronized boolean isSetA1( final long a1Arg )
{
                      if ( a1 == null ) {
                        a1 = a1Arg;
                        conditionallySumArguments();
                        return true;
                      }
                      return false;
                    }


                    private synchronized boolean isSetA2( final long a2Arg )
{
                      if ( a2 == null ) {
                        a2 = a2Arg;
                        conditionallySumArguments();
                        return true;
                      }
                      return false;
                    }


                    private synchronized void conditionallySumArguments()
{ // Works if not synchronized!!!
                      if ( ( a1 == null ) || ( a2 == null ) ) { return; }
                      sum += a1 + a2;
                      a1 = a2 = null;
                    }
                  }


                Thanks in advance for any comments,

                  -- Howard.







            --
              -- Howard.




            _______________________________________________
            Concurrency-interest mailing list
            Concurrency-interest at cs.oswego.edu
            http://cs.oswego.edu/mailman/listinfo/concurrency-interest







        --
          -- Howard.







  --
    -- Howard.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20120106/500052b8/attachment-0001.html>


More information about the Concurrency-interest mailing list