简体   繁体   中英

Java: Synchronization between Outer Class and inner class

I have code similar to following:

class OuterClass
{
   private final AtomicInteger count = new AtomicInteger(0);

   private class InnerClass extends TimerTask
   {
       public void run()
       {
            ......
            ......
            incremenetCount();
       }
   }

   public void doSomething()
   {
        .......
        .......
        incremenetCount();
   }

   private void incrementCount()
   {
      count.incrementAndGet();
   }
}

Is calling incrementCount from inner class the same as calling it from any other function in outer class as the synchronization is actually around the variable count ?

Is calling incrementAndCount from inner class the same as calling it from any other function in outer class [...]

Yes, calling incrementCount() from the inner class is the same as calling incrementCount() from the outer count.

All non-static inner classes have an implicit reference to the object of the enclosing class, and it is through this reference the incrementCount() will be called.

(Story would have been different if your inner class was static though.)

as the synchronization is actually around the variable count?

Doesn't matter. The same method, is called on the same object, regardless if you do the call from the inner or from the outer class.

The short answer is that it is safe.

To understand why, lets look at this:

class SomeClass {
    private final AtomicInteger count = new AtomicInteger(0);
    ...
    private void incrementCount() {
        count.incrementAndGet();
    }
}

There are two questions that need to be considered to determine whether this is thread-safe.

  1. Is the fetch of count properly synchronized? Answer yes - because count is declared as final and there is rule that says that a final field can be read without synchronization once the constructor has completed.

  2. Is the incrementAndGet() method thread-safe? Answer yes - the specification of the AtomicInteger class says so.

Now let us look at the case with the inner class. The instance of inner class has a hidden final reference to the instance of the outer class. So ...

    public void run() {
        incrementCount();
    }

is equivalent to this ...

    private final OuterClass $outer;  // initialized by the constructor.
    ...
    public void run() {
        $outer.incrementCount();
    }

By the reasoning of point 1. above, the incrementCount() call itself is thread-safe. And the fetch of $outer is thread-safe too, because it is implicitly a final field.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM