synchronized中wait、notify的原理与源码

1.wait和notify的流程图

2.JVM源码

java层面wait的方法

 public final native void wait(long timeout) throws InterruptedException;

jvm中object.c

static JNINativeMethod methods[] = {
{"hashCode", "()I", (void *)&JVM_IHashCode},
{"wait", "(J)V", (void *)&JVM_MonitorWait},
{"notify", "()V", (void *)&JVM_MonitorNotify},
{"notifyAll", "()V", (void *)&JVM_MonitorNotifyAll},
{"clone", "()Ljava/lang/Object;", (void *)&JVM_Clone},
};

jvm层面wait方法的源码

JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms))
JVMWrapper("JVM_MonitorWait");
Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
JavaThreadInObjectWaitState jtiows(thread, ms != 0);
if (JvmtiExport::should_post_monitor_wait()) {//默认为false
JvmtiExport::post_monitor_wait((JavaThread *)THREAD, (oop)obj(), ms);
}
ObjectSynchronizer::wait(obj, ms, CHECK);//主要方法是wait
JVM_END

ObjectSynchronizer::wait

// -----------------------------------------------------------------------------
// Wait/Notify/NotifyAll
// NOTE: must use heavy weight monitor to handle wait()
int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
if (UseBiasedLocking) {//使用偏向锁
BiasedLocking::revoke_and_rebias(obj, false, THREAD);//撤销偏向锁,因为第二个参数为false;该方法在synchronized的文章中已经做过介绍了
}
if (millis < 0) {//超时就抛出异常
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
}
//wait方法需要先将锁膨胀到重量级锁
ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD,
obj(),
inflate_cause_wait); DTRACE_MONITOR_WAIT_PROBE(monitor, obj(), THREAD, millis);
monitor->wait(millis, true, THREAD);//插入等待队列中等待 // This dummy call is in place to get around dtrace bug 6254741. Once
// that's fixed we can uncomment the following line, remove the call
// and change this function back into a "void" func.
// DTRACE_MONITOR_PROBE(waited, monitor, obj(), THREAD);
return dtrace_waited_probe(monitor, obj, THREAD);
}

ObjectMonitor::wait

void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
Thread * const Self = THREAD;//获取当前线程对象
JavaThread *jt = (JavaThread *)THREAD;//获取当前线程对应的java线程对象
EventJavaMonitorWait event; Self->_Stalled = intptr_t(this);//设置当前线程阻塞在该 ObjectMonitor上
jt->set_current_waiting_monitor(this); ObjectWaiter node(Self);//生成节点
node.TState = ObjectWaiter::TS_WAIT;//修改状态
Self->_ParkEvent->reset();
OrderAccess::fence(); //全屏障保证后续可以读取到最新值 Thread::SpinAcquire(&_WaitSetLock, "WaitSet - add");//获取_WaitSetLock
AddWaiter(&node);//将等待的节点插入waitset中
Thread::SpinRelease(&_WaitSetLock);//释放_WaitSetLock _Responsible = NULL; intptr_t save = _recursions; // record the old recursion count
_waiters++; // increment the number of waiters
_recursions = 0; // set the recursion level to be 1
exit(true, Self); // exit the monitor 退出重量级锁 int ret = OS_OK;
int WasNotified = 0;
{ // State transition wrappers
OSThread* osthread = Self->osthread();
OSThreadWaitState osts(osthread, true);//将os线程置为OBJECT_WAIT的状态
{
ThreadBlockInVM tbivm(jt);//设置当前对应的java线程是阻塞状态;_thread_blocked = 10, // blocked in vm
// Thread is in thread_blocked state and oop access is unsafe.
jt->set_suspend_equivalent(); if (interruptible && (Thread::is_interrupted(THREAD, false) || HAS_PENDING_EXCEPTION)) {//中断或者异常唤醒不做处理
// Intentionally empty
} else if (node._notified == 0) {//如果唤醒的信号==0;去阻塞
if (millis <= 0) {//如果设置的等待时间<=0
Self->_ParkEvent->park();//阻塞等待唤醒
} else {
ret = Self->_ParkEvent->park(millis);//超时等待,到时间自动醒过来
}
} // were we externally suspended while we were waiting?
if (ExitSuspendEquivalent (jt)) {
// TODO-FIXME: add -- if succ == Self then succ = null.
jt->java_suspend_self();
} } // Exit thread safepoint: transition _thread_blocked -> _thread_in_vm if (node.TState == ObjectWaiter::TS_WAIT) {//如果当前状态时TS_WAIT
Thread::SpinAcquire(&_WaitSetLock, "WaitSet - unlink");//获取_WaitSetLock锁
if (node.TState == ObjectWaiter::TS_WAIT) {
DequeueSpecificWaiter(&node); // 将当前node等待节点从waitset中摘除
node.TState = ObjectWaiter::TS_RUN;//修改状态为TS_RUN
}
Thread::SpinRelease(&_WaitSetLock);//释放_WaitSetLock锁
} OrderAccess::loadload();//使用读屏障,刷新内存中的值 OrderAccess::fence(); Self->_Stalled = 0;//将阻塞对象置为空 ObjectWaiter::TStates v = node.TState;//获取节点状态
if (v == ObjectWaiter::TS_RUN) {//如果节点状态为TS_RUN,去获取锁
enter(Self);
} else {
ReenterI(Self, &node);//尝试去获取锁
node.wait_reenter_end(this);//将线程设置为可运行状态
}
} // OSThreadWaitState() jt->set_current_waiting_monitor(NULL); _recursions = save; // restore the old recursion count 值还原
_waiters--; // decrement the number of waiters 等待节点减1 if (!WasNotified) {//如果不是被唤醒的
// no, it could be timeout or Thread.interrupt() or both
// check for interrupt event, otherwise it is timeout
if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {//中断产生的直接抛出异常
THROW(vmSymbols::java_lang_InterruptedException());
}
}
}

JVM_MonitorNotify和JVM_MonitorNotifyAll

JVM_ENTRY(void, JVM_MonitorNotify(JNIEnv* env, jobject handle))
JVMWrapper("JVM_MonitorNotify");
Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
ObjectSynchronizer::notify(obj, CHECK);//关键方法是notify
JVM_END JVM_ENTRY(void, JVM_MonitorNotifyAll(JNIEnv* env, jobject handle))
JVMWrapper("JVM_MonitorNotifyAll");
Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
ObjectSynchronizer::notifyall(obj, CHECK);//关键方法是notifyAll
JVM_END

ObjectSynchronizer::notify和ObjectSynchronizer::notifyall

void ObjectSynchronizer::notify(Handle obj, TRAPS) {
if (UseBiasedLocking) {//偏向锁直接撤销
BiasedLocking::revoke_and_rebias(obj, false, THREAD);
}
markOop mark = obj->mark();//轻量级锁直接进行替换头部
if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {
return;
}
//锁膨胀直接调用notify方法
ObjectSynchronizer::inflate(THREAD,
obj(),
inflate_cause_notify)->notify(THREAD);
} // NOTE: see comment of notify()
void ObjectSynchronizer::notifyall(Handle obj, TRAPS) {
if (UseBiasedLocking) {//偏向锁直接撤销
BiasedLocking::revoke_and_rebias(obj, false, THREAD);
}
markOop mark = obj->mark();//轻量级锁直接进行替换头部
if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {
return;
}
//锁膨胀直接调用notifyAll方法
ObjectSynchronizer::inflate(THREAD,
obj(),
inflate_cause_notify)->notifyAll(THREAD);
}

ObjectMonitor::notify和 ObjectMonitor::notifyAll

void ObjectMonitor::notify(TRAPS) {
if (_WaitSet == NULL) {//等待集合为空直接返回
return;
}
DTRACE_MONITOR_PROBE(notify, this, object(), THREAD);
INotify(THREAD);//唤醒当前线程
OM_PERFDATA_OP(Notifications, inc(1));
} void ObjectMonitor::notifyAll(TRAPS) {
if (_WaitSet == NULL) {//等待集合为空直接返回
return;
}
DTRACE_MONITOR_PROBE(notifyAll, this, object(), THREAD);
int tally = 0;
while (_WaitSet != NULL) {//while循环挨个唤醒
tally++;
INotify(THREAD);
} OM_PERFDATA_OP(Notifications, inc(tally));
}

ObjectMonitor::INotify

void ObjectMonitor::INotify(Thread * Self) {
Thread::SpinAcquire(&_WaitSetLock, "WaitSet - notify");//获取_WaitSetLock锁
ObjectWaiter * iterator = DequeueWaiter();//第一个节点出队
if (iterator != NULL) {
iterator->TState = ObjectWaiter::TS_ENTER;//修改状态为TS_ENTER iterator->_notified = 1;//标识唤醒线程数为1
iterator->_notifier_tid = JFR_THREAD_ID(Self);//记录唤醒的线程di ObjectWaiter * list = _EntryList;//获取_EntryList执行队列 // prepend to cxq 执行队列为空,将竞争队列中的任务批量移动到_EntryList中
if (list == NULL) {
iterator->_next = iterator->_prev = NULL;
_EntryList = iterator;
} else {
iterator->TState = ObjectWaiter::TS_CXQ;//否则修改节点状态为TS_CXQ
for (;;) {//保证出队的节点插入到等待队列中
ObjectWaiter * front = _cxq;
iterator->_next = front;
if (Atomic::cmpxchg(iterator, &_cxq, front) == front) {
break;
}
}
}
iterator->wait_reenter_begin(this);
}
Thread::SpinRelease(&_WaitSetLock);//释放_WaitSetLock锁 }

4.留言

这些只是个人整理的知识点,中间可能有不到位的地方,烦请各位大佬指出

synchronized中wait、notify的原理与源码的更多相关文章

  1. JDK1.8中LinkedList的实现原理及源码分析

    详见:https://blog.csdn.net/cb_lcl/article/details/81222394 一.概述           LinkedList底层是基于双向链表(双向链表的特点, ...

  2. Java并发包中Semaphore的工作原理、源码分析及使用示例

    1. 信号量Semaphore的介绍 我们以一个停车场运作为例来说明信号量的作用.假设停车场只有三个车位,一开始三个车位都是空的.这时如果同时来了三辆车,看门人允许其中它们进入进入,然后放下车拦.以后 ...

  3. 详解SpringMVC中Controller的方法中参数的工作原理[附带源码分析]

    目录 前言 现象 源码分析 HandlerMethodArgumentResolver与HandlerMethodReturnValueHandler接口介绍 HandlerMethodArgumen ...

  4. 【MVC - 参数原理】详解SpringMVC中Controller的方法中参数的工作原理[附带源码分析]

    前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不熟悉,那么请参考它的入门blog:http://www.cnblogs.com/fangjian0423/p/spring ...

  5. 2、JDK8中的HashMap实现原理及源码分析

    本篇提纲.png 本篇所述源码基于JDK1.8.0_121 在写上一篇线性表的文章的时候,笔者看的是Android源码中support24中的Java代码,当时发现这个ArrayList和Linked ...

  6. JDK1.8中ArrayList的实现原理及源码分析

    一.概述 ArrayList是Java开发中使用比较频繁的一个类,通过对源码的解读,可以了解ArrayList的内部结构以及实现方法,清楚它的优缺点,以便我们在编程时灵活运用. 二.源码分析 2.1 ...

  7. JDK8中的HashMap实现原理及源码分析

    大纲 一.什么是Hash?什么是HashMap? 二.HashMap的内部实现机制 1.HashMap基本元素 ①DEFAULT_INITIAL_CAPACITY&MAXIMUM_CAPACI ...

  8. ConcurrentHashMap实现原理及源码分析

    ConcurrentHashMap实现原理 ConcurrentHashMap源码分析 总结 ConcurrentHashMap是Java并发包中提供的一个线程安全且高效的HashMap实现(若对Ha ...

  9. HashMap和ConcurrentHashMap实现原理及源码分析

    HashMap实现原理及源码分析 哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表, ...

  10. (转)ReentrantLock实现原理及源码分析

    背景:ReetrantLock底层是基于AQS实现的(CAS+CHL),有公平和非公平两种区别. 这种底层机制,很有必要通过跟踪源码来进行分析. 参考 ReentrantLock实现原理及源码分析 源 ...

随机推荐

  1. 3D开发工具HOOPS最新解析合集!助力实现web端高性能模型渲染!

    一.3D技术为创新提供强大助力(1)3D专家提供专属技术支持服务不管您想搭建桌面.WEB或者移动端APP应用,技术领先全球的HOOPS Platform组件都可以为您提供弹性的3D集成架构,同时,一批 ...

  2. PHP__采集类__Snoopy

    Snoopy                                                  目录 了解Snoopy.1 功能:...1 下载Snoopy:...2 Snoopy常用 ...

  3. Auto-GPT测评:自信、努力、不合格

    这两天,Auto-GPT 爆火 https://github.com/Torantulino/Auto-GPT 它是一款让最强语言模型GPT-4能够自主完成任务的模型,让整个AI圈疯了.它的嘴大突破是 ...

  4. 解析草稿-造价管理-工程经济-P190-例4.2.3

    原题 计算步骤 需要记忆的概念 excel计算文件 [腾讯文档]例题

  5. Java的抽象类 & 接口

    抽象类 如果自下而上在类的继承层次结构中上移,位于上层的类更具有通用性,甚至可能更加抽象.从某种角度看,祖先类更加通用,人们只将它作为派生其他类的基类,而不作为想使用的特定的实例类.例如,考虑一下对 ...

  6. 2021-06-21:贩卖机只支持硬币支付,且收退都只支持10 ,50,100三种面额。一次购买只能出一瓶可乐,且投钱和找零都遵循优先使用大钱的原则,需要购买的可乐数量是m, 其中手头拥有的10、50

    2021-06-21:贩卖机只支持硬币支付,且收退都只支持10 ,50,100三种面额.一次购买只能出一瓶可乐,且投钱和找零都遵循优先使用大钱的原则,需要购买的可乐数量是m, 其中手头拥有的10.50 ...

  7. 2021-10-23:位1的个数。编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1‘ 的个数(也被称为汉明重量)。提示:请注意,在某些语言(如 Java)中

    2021-10-23:位1的个数.编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为汉明重量).提示:请注意,在某些语言(如 Java)中 ...

  8. Grafana系列-统一展示-11-Logs Traces无缝跳转

    系列文章 Grafana 系列文章 概述 如前文 Grafana 系列 - 统一展示 -1- 开篇所述, Grafana 可以了解所有相关的数据--以及它们之间的关系--对于尽快根治事件和确定意外系统 ...

  9. Java中synchronized的优化

    本文介绍为了实现高效并发,虚拟机对 synchronized 做的一系列的锁优化措施 高效并发是从 JDK5 升级到 JDK6 后一项重要的改进项,HotSpot 虚拟机开发团队在 JDK6 这个版本 ...

  10. GPT大语言模型Alpaca-lora本地化部署实践【大语言模型实践一】

    模型介绍 Alpaca模型是斯坦福大学研发的LLM(Large Language Model,大语言)开源模型,是一个在52K指令上从LLaMA 7B(Meta公司开源的7B)模型微调而来,具有70亿 ...