在 java 中,在 ClassName.class 而不是 class 实例上同步可能产生的副作用?
In java, possible side effects of synchronizing on ClassName.class instead of on instance of a class?
我的理解是,在 ClassName.class 上同步说 Penguin.class 可能并不总是正确的方法(我的意思是使用 Penguin.class 作为正常的内部锁,除非有意影响Penguin.class) 的静态访问,而不是首选的同步方式是在 penguin 上(Penguin.class 的一个实例)。
如果我使用前一种方法,我会在一段时间内看到所有 Penguin 的静态方法被阻塞(因此除非有意,否则应该避免)。
前一种方法是否也会阻止对静态字段的读写(不这么认为)?
还有其他我遗漏的副作用吗?性能等??
A Class 本质上是一个对象,在运行时只有一个对象。
Class T 是 Class
的对象(实例)
Class 级锁定将阻止多个线程进入使用它的同步块,这与 'Object'.
上的锁定相似。
Will the former approach also block reads and writes to static fields (think not)?
同步从不 阻止读取或写入任何 字段(静态或其他)。唯一会阻塞同步的是,它会阻塞其他线程同时在同一个对象上进行同步。
要想知道在什么对象上同步,就需要了解为什么要同步。
你通常想要同步是因为你有一个数据结构,并且你有一个或多个线程想要修改数据结构,并且任何一个线程都不可能在不临时放置结构的情况下完成它的工作进入不良状态。因此,您通过确保每个修改结构的线程仅在同步时这样做来解决该问题,并且您还确保甚至 查看 结构的每个线程仅在同步时这样做同步。
那么,要同步什么?
那么,你的程序中有多少这样的数据结构?如果只有其中之一,那么您应该只有一个同步对象。 Foobar.class
是一个对象,在您的程序中通常只有一个对象,因此在保护全局数据时,在 Class 对象上同步通常是一个不错的选择。
如果有很多相似的结构,那么每个结构都有自己独立的锁对象通常是有意义的。这样,两个线程可以同时操作两个不同的实例,并且只有在尝试操作同一个实例时才会相互阻塞。
如果您的每个结构都由 Foobar
class 的实例表示,那么最简单的方法是在 foobar 实例上进行同步。一种更复杂的方法是让每个 Foobar
对象都有自己的 private
锁对象:
class Foobar {
private final Object lock = new Object();
...
public SomeType someOperation(...) {
...
synchronized(lock) {
doSomethingThatNeedsProtection();
}
...
}
}
我的理解是,在 ClassName.class 上同步说 Penguin.class 可能并不总是正确的方法(我的意思是使用 Penguin.class 作为正常的内部锁,除非有意影响Penguin.class) 的静态访问,而不是首选的同步方式是在 penguin 上(Penguin.class 的一个实例)。
如果我使用前一种方法,我会在一段时间内看到所有 Penguin 的静态方法被阻塞(因此除非有意,否则应该避免)。
前一种方法是否也会阻止对静态字段的读写(不这么认为)?
还有其他我遗漏的副作用吗?性能等??
A Class 本质上是一个对象,在运行时只有一个对象。
Class T 是 Class
的对象(实例)Class 级锁定将阻止多个线程进入使用它的同步块,这与 'Object'.
上的锁定相似。Will the former approach also block reads and writes to static fields (think not)?
同步从不 阻止读取或写入任何 字段(静态或其他)。唯一会阻塞同步的是,它会阻塞其他线程同时在同一个对象上进行同步。
要想知道在什么对象上同步,就需要了解为什么要同步。
你通常想要同步是因为你有一个数据结构,并且你有一个或多个线程想要修改数据结构,并且任何一个线程都不可能在不临时放置结构的情况下完成它的工作进入不良状态。因此,您通过确保每个修改结构的线程仅在同步时这样做来解决该问题,并且您还确保甚至 查看 结构的每个线程仅在同步时这样做同步。
那么,要同步什么?
那么,你的程序中有多少这样的数据结构?如果只有其中之一,那么您应该只有一个同步对象。 Foobar.class
是一个对象,在您的程序中通常只有一个对象,因此在保护全局数据时,在 Class 对象上同步通常是一个不错的选择。
如果有很多相似的结构,那么每个结构都有自己独立的锁对象通常是有意义的。这样,两个线程可以同时操作两个不同的实例,并且只有在尝试操作同一个实例时才会相互阻塞。
如果您的每个结构都由 Foobar
class 的实例表示,那么最简单的方法是在 foobar 实例上进行同步。一种更复杂的方法是让每个 Foobar
对象都有自己的 private
锁对象:
class Foobar {
private final Object lock = new Object();
...
public SomeType someOperation(...) {
...
synchronized(lock) {
doSomethingThatNeedsProtection();
}
...
}
}