【问题标题】:In java, possible side effects of synchronizing on ClassName.class instead of on instance of a class?在java中,同步ClassName.class而不是类的实例的可能副作用?
【发布时间】:2016-08-30 20:56:05
【问题描述】:

我的理解是,在 ClassName.class 上同步说 Penguin.class 可能并不总是正确的方式(我的意思是使用 Penguin.class 作为普通的内在锁,除非有意影响 Penguin.class 的静态访问)和相反,首选的同步方式是在 penguin(Penguin.class 的一个实例)上。 如果我使用前一种方法,我会看到一段时间内阻塞了 Penguin 的所有静态方法(所以除非是故意的,否则应该避免这种方法)。
前一种方法是否还会阻止对静态字段的读写(认为不会)? 我还缺少其他副作用吗?性能等??

【问题讨论】:

  • Class 实例上同步会阻止所有其他在同一类实例上同步的代码。仅此而已,与在任何其他实例上同步没有什么不同。
  • 你的思维水平太低了。多线程代码很难编写,即使对于聪明人来说也是如此。您最好使用新的并发包并考虑不可变数据。更实用的方法将更安全,更容易正确。让线程改变可变静态字段是自找麻烦。我会重新考虑。
  • @duffymo - 我无法决定这个应用程序的语言,它已经完成了,但永远不会被弄脏。某些或其他的东西永远不会破裂。 FP没做过多,但是一般情况下是否支持多线程,scala是否支持。
  • 你有Java标签;我假设你想要Java。 FP 是否支持多线程?嗯,通常。不需要。 Scala 是一种混合功能/面向对象的语言。自从 JDK 8 添加了 lambdas 以来,Java 本身具有更多的功能特性。
  • Penguin.class 与 Class.class 不同。

标签: java multithreading performance synchronization static-methods


【解决方案1】:

前一种方法是否也会阻止对静态字段的读写(认为不会)?

同步从不阻止对任何字段(静态或其他)的读取或写入。同步阻塞的唯一一点是,它会阻止其他线程同时在同一个对象上同步。

为了知道要在哪个对象上同步,有必要了解为什么要同步。

你通常想要同步,因为你有一个数据结构,并且你有一个或多个线程想要修改数据结构,并且如果不将结构临时放入一个状态不好。因此,您可以通过确保修改结构的每个线程仅在同步时这样做来解决该问题,并且您还要确保即使查看该结构的每个线程也仅在同步时这样做。

那么,要同步什么?

那么,您的程序中有多少这样的数据结构?如果只有一个,那么您应该只有一个同步对象。 Foobar.class 是您的程序中通常只有一个对象,因此在保护全局数据时,在 Class 对象上同步通常是一个不错的选择。

如果有很多类似的结构,那么每个都有自己独立的锁对象通常是有意义的。这样,两个线程可以同时对两个不同的实例进行操作,并且只有在尝试对同一个实例进行操作时才会相互阻塞。

如果每个结构都由 Foobar 类的实例表示,那么最简单的方法是在 foobar 实例上进行同步。更复杂的方法是让每个Foobar 对象拥有自己的private 锁定对象:

class Foobar {
    private final Object lock = new Object();

    ...

    public SomeType someOperation(...) {
        ...
        synchronized(lock) {
             doSomethingThatNeedsProtection();
        }
        ...
    }
}

【讨论】:

  • 在 Foobar.class 上同步将阻塞 Foobar.class 中的所有静态方法。对吧??
  • @samshers,不。它不会阻止任何方法。唯一会阻塞同步的是,它会阻止其他线程同时在同一个对象或类上同步。 (注意:当你编写一个同步的方法时,这只是编写一个主体是一个同步语句的方法的一种简写方式。stackoverflow.com/questions/25642642/…
  • 互斥怎么样。 ...我错过了添加 synchronized 即静态同步方法,然后我希望这些方法被阻止。对吧??
  • @samshers,“互斥”(又名“互斥”)正是我所说的“......阻止其他线程同时在同一个对象上同步”的意思。至于同步方法,请查看我之前评论中的链接:将synchronized 添加到方法声明中只是将方法主体包装在大synchronized 语句中的快捷方式。一旦您了解了 synchronized 语句的作用和不作用,那么同步方法就很容易理解了。
【解决方案2】:

类本质上是一个对象,在运行时中只有一个对象。

类 T 是类的对象(实例)

类级别锁定将防止多个线程进入使用它的同步块,这与锁定“对象”的位置非常相似。

【讨论】:

    猜你喜欢
    • 2022-07-06
    • 1970-01-01
    • 2016-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多