Java &引用;已同步(此)“;vs.“;已同步((基类)this)";在爪哇?
这是我上一个问题的后续问题 对于以下节目Java &引用;已同步(此)“;vs.“;已同步((基类)this)";在爪哇?,java,multithreading,synchronization,Java,Multithreading,Synchronization,这是我上一个问题的后续问题 对于以下节目 Class SubClassB extends SuperClassA { protected int c; public void inc() { synchronized (this) { c++; } } public void dec() { synchronized ( (SuperClassA) this) {
Class SubClassB extends SuperClassA {
protected int c;
public void inc() {
synchronized (this) {
c++;
}
}
public void dec() {
synchronized ( (SuperClassA) this) {
c--;
}
}
}
计数器“c”是线程安全访问的吗?我不确定在“dec()”方法中,超类强制转换“this”引用是否是同步块的有效对象?如果是,两个同步块会锁定同一个“this”对象吗?(在我看来“(超类)this”不等于“this”)
这个奇怪的模拟代码来自下面的真实示例,其中超类是一个不应该修改的基类
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();
}
}
在本例中,子类B中的“dec()”方法调用其超类的“dec()”方法,该方法执行对“this”对象的锁定,我假定该对象为“SuperClassA.this”。如果子类B的“inc()”方法中的锁定对象与子类B的“dec()”方法中的锁定对象不完全相同,那么我想知道子类B中继承的计数器“c”可能无法被不同的线程安全访问。我觉得在同步块中使用“this”引用存在一些歧义
在实际示例中,如果我希望子类B的计数器“c”是线程安全的,是否需要在其“dec()”方法中再添加一个同步块,如下所示
Class SubClassB extends SuperClassA {
public void inc() {
synchronized (this) {
c++;
}
}
public void dec() {
synchronized (this) {
super.dec();
}
}
}
但这样添加的块似乎并不优雅,可能是多余的
有人对这些问题有什么看法吗。提前谢谢
劳伦斯就同步而言,这三个例子都是正确的
this
强制转换为synchronized
中的基类没有任何区别synchronized(this)
并不重要:在这两种情况下使用相同的锁代码是线程安全的,因为
(SomeObject)this
adnthis
是同一个对象。强制转换不会将一个对象转换为另一个对象
不过,该代码缺乏封装,因为它允许任何子类以非同步方式访问受保护的c
字段。因此,任何子类都可以使用c++
或c--
而不进行任何同步。这个领域应该是私有的
在我看来“(超类)this”不等于“this”
错;同步是在对象上完成的,强制转换只会更改编译时类型,对对象标识没有影响
因此,您不必在子类中添加额外的同步
计数器“c”是线程安全访问的吗
是的,它使用相同的锁对象
我不确定在“dec()”方法中,超类强制转换“this”引用是否是同步块的有效对象
对
如果是,两个同步块会锁定同一个“this”对象吗?(在我看来“(超类)this”不等于“this”)
对。即使将实例强制转换为可以强制转换为的对象(甚至是对象),它仍然会引用同一个对象
[…]但似乎这样添加的块并不优雅,可能是多余的
这是多余的。只有在调用多个同步方法且组合效果必须是原子的情况下,才需要额外的同步。感谢您提醒我计数器“c”应声明为“私有”。现在我知道“(超级类)this”和“this”具有不同的编译时类型,但在同步块中持有相同的锁。感谢您的快速响应,并提醒我任何对象只有一个监视器。