简体   繁体   English

“同步(this)”与“synchronized((BaseClass)this)”在Java中?

[英]“synchronized(this)” vs. “synchronized((BaseClass)this)” in Java?

This is a successor of my previous question, Is this variable being safely accessed by using synchronization? 这是我之前问题的继承者, 是否可以通过同步安全地访问此变量?

For the following program, 对于以下程序,

Class SubClassB extends SuperClassA {
     protected int c;

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

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

Would the counter "c" be accessed thread safe ? 计数器“c”是否可以访问线程安全? I am not sure that in the "dec()" method, is the SuperClassA cast "this" reference a valid object for the synchronized block ? 我不确定在“dec()”方法中,SuperClassA是否将“this”引用为synchronized块的有效对象? If yes, would the two synchronized blocks lock the same "this" object ? 如果是,两个同步块是否会锁定相同的“this”对象? (As it seems to me that "(SuperClassA) this" is not equal to "this") (在我看来,“(SuperClassA)这个”不等于“这个”)

This strange simulated code comes from the following real life example where SuperClassA is a base class that is not supposed to be modified, 这个奇怪的模拟代码来自以下现实生活中的例子,其中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();
     }
}

In this example, the "dec()" method in SubClassB calls its superclass's "dec()" method which performs a lock to a "this" object that I suppose to be "SuperClassA.this". 在这个例子中,SubClassB中的“dec()”方法调用它的超类的“dec()”方法,该方法执行对“this”对象的锁定,我认为该对象是“SuperClassA.this”。 If the locked object in SubClassB's "inc()" method is not exactly the same as the locked object in SubClassB's "dec()" method, then I am wondering the inherited counter "c" in SubClassB may NOT be safely accessed by different threads. 如果SubClassB的“inc()”方法中的锁定对象与SubClassB的“dec()”方法中的锁定对象不完全相同,那么我想知道SubClassB中的继承计数器“c”可能不会被不同的线程安全地访问。 I feel that there is some ambiguities in using the "this" reference in synchronized blocks. 我觉得在同步块中使用“this”引用有一些含糊之处。

In the real life example, if I want SubClassB's counter "c" to be thread safe, do I need to add one more synchronized block in its "dec()" method, like this, 在现实生活中的例子中,如果我希望SubClassB的计数器“c”是线程安全的,我是否需要在其“dec()”方法中再添加一个synchronized块,如下所示,

Class SubClassB extends SuperClassA {

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

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

But it seems that such added block is not elegant and may be redundant ! 但似乎这样的附加块并不优雅,可能是多余的!

Does anyone have some ideas on these questions. 有没有人对这些问题有一些想法。 Thanks in advance. 提前致谢。

Lawrence 劳伦斯

The code is thread-safe, because (SomeObject) this adn this are the same object. 代码是线程安全的,因为(SomeObject) this this是同一个对象。 A cast doesn't transform an object into another object. 强制转换不会将对象转换为另一个对象。

The code lacks encapsulation, though, because it lets any subclass access the protected c field in an unsynchronized way. 但是,代码缺少封装,因为它允许任何子类以不同步的方式访问受保护的c字段。 So, any subclass might use c++ or c-- without any synchronization. 因此,任何子类都可以使用c++c--而无需任何同步。 The field should be private. 该领域应该是私人的。

Would the counter "c" be accessed thread safe ? 计数器“c”是否可以访问线程安全?

Yes, it's using the same lock object. 是的,它使用相同的锁定对象。

I am not sure that in the "dec()" method, is the SuperClassA cast "this" reference a valid object for the synchronized block ? 我不确定在“dec()”方法中,SuperClassA是否将“this”引用为synchronized块的有效对象?

Yes. 是。

If yes, would the two synchronized blocks lock the same "this" object ? 如果是,两个同步块是否会锁定相同的“this”对象? (As it seems to me that "(SuperClassA) this" is not equal to "this") (在我看来,“(SuperClassA)这个”不等于“这个”)

Yes. 是。 Even if you cast the instance to something it can be casted to (even Object), it'll still refer to the same object. 即使你将实例转换为可以转换为(甚至是Object)的东西,它仍然会引用同一个对象。

[...] But it seems that such added block is not elegant and may be redundant ! [...]但似乎这样的附加块并不优雅,可能是多余的!

It is redundant. 这是多余的。 Extra synchronization is required only if you call multiple synchronized methods and the combined effect must be atomic. 只有在调用多个同步方法且组合效果必须为原子时,才需要进行额外同步。

it seems to me that "(SuperClassA) this" is not equal to "this" 在我看来,“(SuperClassA)这个”不等于“这个”

Wrong; 错误; synchronization is done on objects, and casting only changes the compile-time type, is has no effect on object identity. 同步是在对象上完成的,而cast只改变编译时类型,对对象标识没有影响。

Thus, you don't have to add an extra synchronization in the subclass. 因此,您不必在子类中添加额外的同步。

All three examples are correct as far as synchronization is concerned. 就同​​步而言,所有三个示例都是正确的。

  1. There's only one monitor associated with any object. 只有一个监视器与任何对象相关联。
  2. Casting this to a base class inside synchronized makes no difference. this转换为synchronized内的基类没有任何区别。
  3. For the same object, it doesn't matter whether synchronized(this) is invoked in the context of the derived class or the base class: the same lock is used in both cases. 对于同一个对象,在派生类或基类的上下文中是否调用synchronized(this)并不重要:在两种情况下都使用相同的锁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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