JVM 中 .class 个对象的同步范围
Scope of synchronization on .class objects in the JVM
假设我有以下代码:
synchronize (Test.class) {
...
}
- 这是否意味着每个
Test.class
对象都被锁定
同一虚拟机中的其他程序 运行?或者这样做
锁只影响 JVM 中的这一个程序?
- 如果它影响每个程序:当
Test.class
处于两个程序通过不同但内容相同的 JAR 包含的依赖项时,锁是否仍会影响两个程序?
Java 是一种 OO 语言,这意味着您拥有对象,它们相互交互以形成一个完整的程序。每个对象都与一个监视器相关联。同步基本上是在对象监视器上实际获得锁定的对象上完成的。
现在回答你的问题。当你说
synchronize (Test.class) {
...
}
锁是在 Test.class 对象上获得的。此外,对于完全限定的 class 名称,JVM 将确保每个 class 加载程序只加载一次(除非它是 GCed)。因此,每个 JVM 实例始终只有一个 Test.class
实例(考虑到 class 加载是由相同的 class 加载完成的)。我所说的 JVM 实例是指 Java 进程,它将拥有自己的 PID。如果一个线程锁定 Test.class
除非它被持有线程释放,否则其他线程无法获得此锁(同一线程可以再次获得锁 - Java 中的锁是可重入性质的)。
如果你启动新的java进程 -> 新的JVM实例 -> Test.class
的新实例被class加载器加载 -> 它的锁可以获得并且不依赖在任何其他 JVM 实例上 运行.
注意 :如果 Class 对象是分开的(例如,相同的 class 由不同的 class 加载程序加载 - 就像万一发生的情况网络应用程序)那么你当然可以在每个应用程序上单独锁定。您将无法将一个 class 的实例转换为另一个
你的 "programs" 只是你多次 运行 的不同 ClassLoader.load(programClass).main(args)
。当然,它们共享一个类加载器、一台机器并且实际上是同一程序的不同部分,一个 OS 进程。只是调用各种 类 programs
没有任何改变。他们仍然彼此可见。如果一个人可以执行另一个人的方法,他们可以互相阻塞。
当您有多个类加载器时,每个类加载器都可以拥有自己的 class 实例(或共享 class 的实例),例如String.class
将被共享,但 MyType.class
可能在每个 "Application" 中不同,假设每个应用程序都有自己的 class 加载程序。
在锁定方面,Class
对象除了在 static synchronised
方法中隐式使用外,没有什么特别之处。
例如
class MyType {
static synchronized void method() { }
}
与
大同小异
class MyType {
static void method() {
synchronized(MyType.class) {
}
}
}
它执行相同的功能,尽管字节码不相同。
假设我有以下代码:
synchronize (Test.class) {
...
}
- 这是否意味着每个
Test.class
对象都被锁定 同一虚拟机中的其他程序 运行?或者这样做 锁只影响 JVM 中的这一个程序? - 如果它影响每个程序:当
Test.class
处于两个程序通过不同但内容相同的 JAR 包含的依赖项时,锁是否仍会影响两个程序?
Java 是一种 OO 语言,这意味着您拥有对象,它们相互交互以形成一个完整的程序。每个对象都与一个监视器相关联。同步基本上是在对象监视器上实际获得锁定的对象上完成的。
现在回答你的问题。当你说
synchronize (Test.class) {
...
}
锁是在 Test.class 对象上获得的。此外,对于完全限定的 class 名称,JVM 将确保每个 class 加载程序只加载一次(除非它是 GCed)。因此,每个 JVM 实例始终只有一个 Test.class
实例(考虑到 class 加载是由相同的 class 加载完成的)。我所说的 JVM 实例是指 Java 进程,它将拥有自己的 PID。如果一个线程锁定 Test.class
除非它被持有线程释放,否则其他线程无法获得此锁(同一线程可以再次获得锁 - Java 中的锁是可重入性质的)。
如果你启动新的java进程 -> 新的JVM实例 -> Test.class
的新实例被class加载器加载 -> 它的锁可以获得并且不依赖在任何其他 JVM 实例上 运行.
注意 :如果 Class 对象是分开的(例如,相同的 class 由不同的 class 加载程序加载 - 就像万一发生的情况网络应用程序)那么你当然可以在每个应用程序上单独锁定。您将无法将一个 class 的实例转换为另一个
你的 "programs" 只是你多次 运行 的不同 ClassLoader.load(programClass).main(args)
。当然,它们共享一个类加载器、一台机器并且实际上是同一程序的不同部分,一个 OS 进程。只是调用各种 类 programs
没有任何改变。他们仍然彼此可见。如果一个人可以执行另一个人的方法,他们可以互相阻塞。
当您有多个类加载器时,每个类加载器都可以拥有自己的 class 实例(或共享 class 的实例),例如String.class
将被共享,但 MyType.class
可能在每个 "Application" 中不同,假设每个应用程序都有自己的 class 加载程序。
在锁定方面,Class
对象除了在 static synchronised
方法中隐式使用外,没有什么特别之处。
例如
class MyType {
static synchronized void method() { }
}
与
大同小异class MyType {
static void method() {
synchronized(MyType.class) {
}
}
}
它执行相同的功能,尽管字节码不相同。