`
grzrt
  • 浏览: 188893 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java 中的 wait 和 notify 实现的源码分析

    博客分类:
  • JAVA
 
阅读更多

在Oracle JVM 1.6 里面实现的object的wait 和notify方法是在synchronizer.cpp里实现。

先介绍2个对象:

1. ObjectMonitor 对象 主要用来监视创立的Object

在synchronizer.cpp 里定义了,ObjectMonitor 的对象,我们来看ObjectMonitor的对象的结构体


ObjectMonitor::ObjectMonitor() {
_header = NULL;
_count = 0;
_waiters = 0,
_recursions = 0;
_object = NULL;
_owner = NULL;
_WaitSet = NULL;
_WaitSetLock = 0 ;
_Responsible = NULL ;
_succ = NULL ;
_cxq = NULL ;
FreeNext = NULL ;
_EntryList = NULL ;
_SpinFreq = 0 ;
_SpinClock = 0 ;
OwnerIsThread = 0 ;
}


每个object的对象里 markOop->monitor() 里可以保存ObjectMonitor的对象。

建立ObjectMonitor的算法:

如果不存在,可以向Thread 的ObjectMonitor 的对象列表中Allocate free objectMonitor 对象。

每个线程都有ObjectMonitor 的free和used的objectMonitor对象列表,如果没有free objectMonitor对象列表,将向global 中ListLock Allocate为了提高效率。

2. ObjectWaiter 对象

ObjectWaiter 对象
class ObjectWaiter : public StackObj {
public:
enum TStates { TS_UNDEF, TS_READY, TS_RUN, TS_WAIT, TS_ENTER, TS_CXQ } ;
enum Sorted { PREPEND, APPEND, SORTED } ;
ObjectWaiter * volatile _next;
ObjectWaiter * volatile _prev;
Thread* _thread;
ParkEvent * _event;
volatile int _notified ;
volatile TStates TState ;
Sorted _Sorted ; // List placement disposition
bool _active ; // Contention monitoring is enabled
public:
ObjectWaiter(Thread* thread) {
_next = NULL;
_prev = NULL;
_notified = 0;
TState = TS_RUN ;
_thread = thread;
_event = thread->_ParkEvent ;
_active = false;
assert (_event != NULL, "invariant") ;
}
void wait_reenter_begin(ObjectMonitor *mon) {
JavaThread *jt = (JavaThread *)this->_thread;
_active = JavaThreadBlockedOnMonitorEnterState::wait_reenter_begin(jt, mon);
}
void wait_reenter_end(ObjectMonitor *mon) {
JavaThread *jt = (JavaThread *)this->_thread;
JavaThreadBlockedOnMonitorEnterState::wait_reenter_end(jt, _active);
}
};


ObjectWaiter 对象里存放thread(线程对象) 和 ParkEvent(线程的unpark), 每一个等待锁的线程都会有一个ObjectWaiter对象.

而objectwaiter是个双向链表结构的对象。

我们可以看到在ObjectMonitor对象里有2个队列成员_WaitSet 和 _EntryList 存放的就是ObjectWaiter

_WaitSet:

主要存放所有wait的线程的对象,也就是说如果有线程处于wait状态,将被挂入这个队列

_EntryList:

所有在等待获取锁的线程的对象,也就是说如果有线程处于等待获取锁的状态的时候,将被挂入这个队列。

Wait 方法实现:

ObjectSynchronizer::wait方法

通过object的对象中找到ObjectMonitor对象

调用方法

void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS)

通过ObjectMonitor::AddWaiter调用把新建立的ObjectWaiter对象放入到 _WaitSet 的队列的末尾中

然后在ObjectMonitor::exit释放锁,接着 thread_ParkEvent->park 也就是wait

Notify方法的实现:

ObjectSynchronizer::notify方法

调用ObjectSynchronizer::inflate

object的对象中找到ObjectMonitor对象

然后调用方法ObjectMonitor::notify

调用ObjectMonitor::DequeueWaiter 摘除第一个ObjectWaiter对象从_WaitSet 的队列中

并把这个ObjectWaiter对象放入_EntryList中,_EntryList 存放的是ObjectWaiter的对象列表,列表的大小就是那些所有在等待这个对象锁的线程数。

注意这里并没有调用ObjectMonitor::exit释放锁

NotifyALL和Notify 的区别就是

通过遍历调用ObjectMonitor::DequeueWaiter,把所有的_WaitSet的队列中的ObjectWaiter对象放入到_EntryList中

关于放入到_EntryList的策略大概有4中Policy,其中还涉及到一个_cxq的队列,先不具体介绍了

notify, 和notifyAll 都没有释放对象的锁,而是在Synchronizer同步块结束的时候释放

如何释放锁

调用ObjectMonitor::exit

从_EntryList里找到一个ObjectWaiter,因为ObjectWaiter里有线程的_event ParkEvent,调用unpark() 通知ObjectWaite里的线程运行(拿到锁),具体实现在ObjectMonitor::ExitEpilog方法里

分享到:
评论

相关推荐

    java源码分析

    从给定的文件片段中,我们可以提取出关于Java中Object类和String类的源码分析的知识点。 首先,Object类是Java中所有类的根类。它包含了所有对象共有的方法,是所有类继承结构的最顶层。从文件片段中我们可以看到...

    java多线程并发实战和源码

    Java多线程并发实战与源码分析是Java开发中至关重要的一部分,它涉及到程序性能优化、系统资源高效利用以及复杂逻辑的正确同步。本书主要聚焦于Java多线程的基础理论和实际应用,虽然书中实例和源码相对较少,但仍然...

    疯狂Java实战演义【书+源码】(疯狂Java讲义课后习题项目)

    源码分析可以帮助读者理解和运用这些机制,编写出高效、安全的并发程序。 文件I/O操作在任何编程语言中都是必不可少的。Java的File类和InputStream/OutputStream家族提供了丰富的功能,用于读写文件和处理流。通过...

    Java常用类源码

    `run()`方法是线程执行的主要入口,`synchronized`关键字用于控制并发访问,`wait()`和`notify()`方法实现线程间的通信。 5. `IOException` 和 `Exception` 类:Java异常处理机制的核心在于`Exception`类及其子类。...

    Java2核心技术卷一 配套源码

    Java提供了内置的多线程支持,源码中会有并发编程的相关示例,包括线程的创建、同步机制(如synchronized关键字、wait/notify机制)以及并发工具类的使用。 I/O流是Java处理输入输出的重要部分,包括文件操作、网络...

    thinking in java 第四版 源码

    源码是程序员与计算机交流的语言,通过阅读和分析《Thinking in Java》的源码,我们可以更直观地理解书中的编程思想和设计模式。第四版的源码反映了Java SE 5.0及之后的版本特性,如枚举类型、泛型、注解等,这些都...

    java基础 Head First Java 及源码

    《Head First Java》是入门Java编程的一本经典...源码分析是学习Java的重要环节,通过阅读和实践书中的例子,你可以更好地理解这些概念如何在实际代码中应用。同时,不断练习编写和调试程序,才能真正掌握Java编程。

    JAVA基础项目视频+源码

    - Java提供了Thread类和Runnable接口来创建和管理线程,理解线程同步和互斥的概念,如synchronized关键字和wait/notify机制。 7. **网络编程**: - 使用Socket编程实现客户端和服务器之间的通信,理解TCP和UDP...

    java入门学习源码

    Java是一种广泛使用的面向...通过分析"Java入门学习源码"中的JavaProject,初学者可以逐步掌握上述知识点,从而建立起扎实的Java编程基础。实际操作这些代码,结合理论学习,将有助于提高编程技能并加深对Java的理解。

    java并发源码分析之实战编程

    "java并发源码分析之实战编程"这个主题深入探讨了Java平台上的并发处理机制,旨在帮助开发者理解并有效地利用这些机制来提高程序性能和可扩展性。在这个专题中,我们将围绕Java并发库、线程管理、锁机制、并发容器...

    Java并发编程从入门到精通源码.rar

    总的来说,这个资源包涵盖了Java并发编程的核心概念和技术,结合源码分析,学习者可以深入理解并发编程的原理,提升在实际项目中的应用能力。通过实践和调试源码,可以更好地掌握这些知识点,提高解决问题的能力。

    java2全方位学习源码

    6. **多线程**:Java提供了强大的多线程支持,包括Thread类、Runnable接口,以及synchronized关键字、wait()、notify()等同步控制方法。源码会展示如何创建和管理线程,实现并发编程。 7. **网络编程**:Java的...

    疯狂Java flashget源码

    Java提供了多种线程同步机制,如synchronized关键字、wait()、notify()和notifyAll()方法,以及Semaphore、CyclicBarrier等高级并发工具。 2. **并发下载策略**:在FlashGet的实现中,关键在于如何有效地分配和管理...

    corejava 源码

    理解源码可以让我们知道如何控制线程的执行顺序,同步机制如`synchronized`关键字和`wait()`, `notify()`方法的使用。 6. **输入/输出流**:Java的I/O系统支持文件操作、网络通信等多种数据传输。`InputStream`和`...

    java疯狂讲义源码

    6. **多线程编程**:Java提供了丰富的多线程支持,源码会展示如何创建和管理线程,同步机制如synchronized关键字和wait()、notify()方法的运用。 7. **网络编程**:Java的Socket编程是实现网络应用的基础,源码可能...

    Java开发实战经典带源码.rar

    5. **多线程编程**:Java提供了强大的多线程支持,书中的相关章节会讲解线程的创建、同步机制(如synchronized关键字、wait/notify机制)、线程池等,帮助读者理解和编写并发程序。 6. **网络编程**:Java提供了...

    Head First Java源码

    7. **多线程**:Java支持并发编程,书中会介绍如何创建和管理线程,包括同步机制(如synchronized关键字和wait/notify机制)以及线程池的使用。 8. **泛型**:泛型是Java 5引入的新特性,它允许在类、接口和方法中...

    《JAVA项目实例源码》

    总而言之,《JAVA项目实例源码》提供了一个全面的学习平台,通过分析和理解这些源码,我们可以提升自己的Java编程技能,更好地掌握实际项目开发中的各种技术,为今后的Java职业生涯打下坚实的基础。而文件"sl"(实例...

    Java大全源码包

    5. **多线程**:Java提供了内置的多线程支持,源码包可能包含线程的创建、同步和通信实例,如synchronized关键字、wait()、notify()和notifyAll()方法的使用。 6. **I/O流**:Java的I/O流系统用于处理输入输出操作...

    Java经典源码实例

    7. **多线程**:学习如何创建和管理线程,理解线程同步和通信,如synchronized关键字、wait()、notify()和notifyAll()方法的应用。 8. **网络编程**:掌握Socket编程,创建TCP和UDP通信,实现简单的客户端和服务端...

Global site tag (gtag.js) - Google Analytics