2012-01-05 77 views
10

这是我刚才的问题的继任者,Is this variable being safely accessed by using synchronization?“synchronized(this)”与“synchronized((BaseClass)this)”in Java?

对于下面的程序,

Class SubClassB extends SuperClassA { 
    protected int c; 

    public void inc() { 
      synchronized (this) { 
       c++; 
      } 
    } 

    public void dec() { 
      synchronized ((SuperClassA) this) { 
       c--; 
      } 
    } 
} 

会反“C”来访问线程安全的?我不确定在“dec()”方法中,SuperClassA将“this”引用转换为同步块的有效对象吗?如果是的话,两个同步块是否会锁定相同的“this”对象? (在我看来,“(SuperClassA)这个”不等于“这个”)

这个奇怪的模拟代码来自下面的现实生活中的例子,其中SuperClassA是一个不应该被修改的基类,

Class SuperClassA { 
    protected int c; 

    public void dec() { 
      synchronized (this) { 
       c--; 
      } 
    } 
} 

Class SubClassB extends SuperClassA { 

    public void inc() { 
      synchronized (this) { 
       c++; 
      } 
    } 

    public void dec() { 
      super.dec(); 
    } 
} 

在这个例子中,在SubClassB了“分解()”方法调用其执行锁定到一个“这个”对象,我想是“SuperClassA.this”其超类的“分解()”方法。如果SubClassB的锁定对象“INC()”方法是不完全一样SubClassB的“DEC()”方法锁定的对象,那么我想知道在SubClassB继承反“C”可以不通过不同的线程安全地访问。我觉得在同步块中使用“this”引用有一些含糊之处。

在现实生活中的例子,如果我想SubClassB的反“C”线程安全的,我需要补充一个synchronized块在其“DEC()”方法,这样,

Class SubClassB extends SuperClassA { 

    public void inc() { 
      synchronized (this) { 
       c++; 
      } 
    } 

    public void dec() { 
      synchronized (this) { 
       super.dec(); 
      } 
    } 
} 

但是看起来这样的增加块不够高雅,可能是多余的!

有没有人对这些问题的一些想法。提前致谢。

劳伦斯

回答

5

将计数器“c”访问线程安全吗?

是的,它使用相同的锁定对象。

我不确定在“dec()”方法中,SuperClassA是否为此同步块引用了“this”引用的有效对象?

是的。

如果是,两个同步块会锁定相同的“this”对象吗? (在我看来,“(SuperClassA)this”不等于“this”)

是的。即使您将实例转换为可以转换为(甚至是Object)的实例,它仍然会引用同一个对象。

[...]但似乎这样添加的块不够高雅,可能是多余的!

它是多余的。只有在您调用多个同步方法并且组合效果必须为原子时,才需要额外同步。

+0

感谢您的回答。 – user1129812 2012-01-05 14:51:34

2

就同步而言,所有三个例子都是正确的。

  1. 这里只有一个与任何对象关联监视器。
  2. 铸造this基类内​​没什么区别。
  3. 出于同样的目的,它并不重要synchronized(this)是否在派生类或基类的上下文中调用:同样锁在两种情况下使用。
+0

感谢您的快速响应,并提醒我只有一个监视器与任何对象。 – user1129812 2012-01-05 14:47:47

6

该代码是线程安全的,因为(SomeObject) thisthis是相同的对象。强制转换不会将对象转换为另一个对象。

代码缺乏封装,但是,因为它可以让任何的子类访问受保护的c场以非同步的方式。因此,任何子类都可以使用c++c--而不进行任何同步。该字段应该是私人的。

+0

感谢您提醒我,柜台“c”应宣布为“私人”。 – user1129812 2012-01-05 14:38:04

3

它在我看来, “(SuperClassA)这种” 不等于 “这个”

错误的;同步是在对象上完成的,并且只会更改编译时类型,对对象标识没有影响。

因此,您不必在子类中添加额外的同步。

+0

现在我知道“(SuperClassA)这个”和“this”是不同的编译时类型,但在同步块中保持相同的锁。 – user1129812 2012-01-05 14:42:30