为什么在子类中同步超类的静态成员是无效的?

huangapple go评论70阅读模式
英文:

Why is it ineffective to synchronize statics of superclass in a subclass?

问题

我正在阅读《Java并发编程 设计原则与模式》一书,作者是Doug Lea。他提到:

每个类关联的静态锁与任何其他类(包括其超类)的锁无关。在子类中添加一个试图保护超类中声明的静态字段的新的静态同步方法是无效的。请改用显式的代码块版本。

为什么这样做是无效的?为什么显式的代码块版本是有效的呢?

英文:

I'm reading "Concurrent programming in Java Design Principles and Patterns", by Doug Lea. And he says:

> The static lock associated with each class is unrelated to that of any
> other class, including its superclasses. It is not effective to add a
> new static synchronized method in a subclass that attempts to protect
> static fields declared in a superclass. Use the explicit block version
> instead.

Why is it ineffective? Why is the explicit block version effective?

答案1

得分: 8

为了保护超类的静态字段,您需要一个共同的锁。如果您编写修改超类字段的类,而其他人编写影响超类字段的子类,您希望确保两个代码片段引用同一把锁。如果它们分别在各自的子类上加锁,就没有共同的锁,它们仍然可能相互干扰。这就是Lea在他说“与任何其他类(包括其超类)的类无关”的意思。

理想情况下,我们希望在定义静态变量的类中执行所需的任何锁定,并保持封装性。然而,显然这个理想情况可能行不通,子类可能需要定义锁定,但需要有一个通用的策略来确定使用哪个锁。

如果您创建一个带有static synchronized的方法,那么它将获取在您定义该方法的类上的锁。如果您要保护的内容不在该类中而在超类中,那就不是您想要的,您希望获取超类的锁,其中声明了需要保护的字段。

指定正确的超类的方法是使用“显式块语法”,如下所示:

synchronized(Superclass.class) {
    ...
}
英文:

For you to protect the superclass static fields, you need a common lock. If you write your class that modifies the superclass fields, and someone else writes a subclass that affects the superclass fields, you want to make sure both pieces of code reference the same lock. If they each lock on their own subclass there is no common lock and they can still interfere with each other. That is what Lea means when he says

> The static lock associated with each class is unrelated to that of any other class, including its superclasses.

Ideally we'd want to do whatever locking was needed in the class that defined the static variables and keep everything encapsulated. Apparently this ideal may not work out though, and subclasses may have to define the locking, but need to have a common policy for what lock to use.

If you create a method with static synchronized then that will acquire the lock on the class you defined the method on. If what you want to protect is not in that class but in the superclass, that's not what you want, you want to acquire the lock for the superclass where the fields that need protecting are declared.

The way to specify the correct superclass is to use the "explicit block syntax", like this:

synchronized(Superclass.class) {
    ...
}

huangapple
  • 本文由 发表于 2020年10月8日 04:46:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/64252074.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定