[concurrency-interest] Nested synchronized

David Holmes davidcholmes at aapt.net.au
Thu Jan 5 20:00:06 EST 2012


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.

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


More information about the Concurrency-interest mailing list