Java:外部类和内部类之间的同步

时间:2012-04-25 04:44:48

标签: java synchronization

我的代码类似于以下内容:

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();
   }
}

从内部类调用incrementCount与从外部类中的任何其他函数调用它是一样的,因为同步实际上是在变量count周围吗?

2 个答案:

答案 0 :(得分:5)

  

从内部类调用incrementAndCount与从外部类中的任何其他函数调用它相同[...]

是的,从内部类调用incrementCount()与从外部调用incrementCount()调用相同。

所有非静态内部类都隐含引用封闭类的对象,并且通过此引用将调用incrementCount()

(如果您的内部类是静态,故事会有所不同。)

  

因为同步实际上是在变量计数附近吗?

没关系。无论你是从内部还是从外部类进行调用,都会在同一个对象上调用相同的方法。

答案 1 :(得分:3)

简短的回答是它是安全的。

要理解原因,让我们来看看:

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

需要考虑两个问题来确定这是否是线程安全的。

  1. count的提取是否正确同步?回答是 - 因为count被声明为final并且有一条规则说明,一旦构造函数完成,就可以在没有同步的情况下读取final字段。

  2. incrementAndGet()方法是否是线程安全的?回答是 - AtomicInteger类的规范是这样说的。

  3. 现在让我们看一下内部类的情况。内部类的实例具有对外部类的实例的隐藏最终引用。所以...

        public void run() {
            incrementCount();
        }
    

    相当于......

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

    通过上面第1点的推理,incrementCount()调用本身是线程安全的。而$outer的获取也是线程安全的,因为它隐含地是final字段。

相关问题