在Java中,Object
和Thread
是独立的类。虽然我们有wait()
/notify()
方法,但JavaObject
源代码没有提到任何关于monitor/Thread
的内容。
所以问题是Object
的监视器如何知道获取它的线程的详细信息?这些信息存储在哪里?对象和线程是如何链接的?
一般来说,这取决于实现。
Object
和Thread
的Java代码只做了相当肤浅的工作。但真正的工作是通过本地方法完成的。
Java语言规范指定了对象监视器及其等待集的行为方式,但没有指定如何实现。
此外,尽管Java虚拟机有命令monitorenter
和monitorexit
,但JVM规范说:
监视器与对象的关联可以通过各种方式进行管理超出本规范范围的方式。例如,监视器可以与对象或者,可以在此时动态分配当线程试图获得对对象的独占访问时在以后某个时间,当监视器中没有线程时释放对象
Java编程语言的同步结构除了入口和出口之外,还需要对监视器上的操作提供支持。其中包括在监视器上等待(
Object.wait
)和通知其他在监视器上等待的线程(Object.notifyAll
和Object.notify
)。标准中支持这些操作Java虚拟机附带的包CCD_ 15。不指令集中显示了对这些操作的明确支持Java虚拟机
这一切都相当于一件事:如何实现一个对象,它的头中有什么,它的监视器是如何实现的,以及wait()
和notify()
方法是如何实现,都完全取决于编写特定JVM的程序员。Oracle(继承自Sun)的实现可能与IBM或IcedTea的实现完全不同。
此外,即使对于同一个编程团队,JVM可用的各种操作系统之间的实现细节也不同。原因很清楚:JVM依赖于操作系统的线程机制来实现其线程,并且每个操作系统都以非常不同的方式提供对线程的访问。
因此,为Windows编写线程实现的程序员所做的事情与为Linux或MacOS X编写线程实施的程序员截然不同。线程可能以不同的方式锁定,因此操作系统之间的监视器可能完全不同。
综上所述:
- 对象的监视器和该监视器的等待集的行为方式在Java语言规范中定义
- 线程管理依赖于操作系统。因此,它必须在本机级别实现,而不是在Java语言本身中实现
- 保存监视器所需的数据结构、保存监视器的当前线程、等待集等也都在本机级别上,并且在操作系统之间和JVM实现之间可能有所不同
- Oracle在自己的JVM中实现这一切的方式并不一定是唯一正确的方式,所有其他实现都遵循这种方式