从源码角度分析java 的 sleep()和wait()究竟有什么区别?
来源:互联网 发布:vmware mac os x 优化 编辑:程序博客网 时间:2024/05/16 09:41
如果不能从根本上理解sleep() 和wait() 之间的区别,再好的解释也会只是当时记得,而后就忘记。本文刨根问题,从源码角度去理解这两个函数的区别。
1. sleep() 的根本实现
jvm sleep()---->jni sleep()--------> 经过层层调用,最终会进入系统的sys_pasue()调用,而sys_pause() 则会调用 schedule(), schedule() 则会主动放弃cpu 时间片,进入等待队列
asmlinkage int sys_pause(void){current->state = TASK_INTERRUPTIBLE;schedule();return -ERESTARTNOHAND;}
2. wait() 的根本实现
先查看jdk\src\share\native\java\lang\Object.c
#include <stdio.h>#include <signal.h>#include <limits.h>#include "jni.h"#include "jni_util.h"#include "jvm.h"#include "java_lang_Object.h"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},};
可以看到wait 对应的是 native 方法是JVM_MonitorWait, 继续查看JVM_MonitorWait的实现
JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms)) JVMWrapper("JVM_MonitorWait"); Handle obj(THREAD, JNIHandles::resolve_non_null(handle)); //调用 JNIHandles::resolve_non_null 函数将 jobject 类型的 handle 转化为 oop assert(obj->is_instance() || obj->is_array(), "JVM_MonitorWait must apply to an object"); JavaThreadInObjectWaitState jtiows(thread, ms != 0); if (JvmtiExport::should_post_monitor_wait()) { JvmtiExport::post_monitor_wait((JavaThread *)THREAD, (oop)obj(), ms); } ObjectSynchronizer::wait(obj, ms, CHECK); //重点分析这句JVM_END
接着分析ObjectSynchronizer::wait()方法
void ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) { if (UseBiasedLocking) { BiasedLocking::revoke_and_rebias(obj, false, THREAD); assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now"); } if (millis < 0) { TEVENT (wait - throw IAX) ; THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative"); } ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj()); 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 and remove the call */ // DTRACE_MONITOR_PROBE(waited, monitor, obj(), THREAD); dtrace_waited_probe(monitor, obj, THREAD);}
void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { ...... // create a node to be put into the queue // Critically, after we reset() the event but prior to park(), we must check // for a pending interrupt. ObjectWaiter node(Self); node.TState = ObjectWaiter::TS_WAIT ; Self->_ParkEvent->reset() ; OrderAccess::fence(); // ST into Event; membar ; LD interrupted-flag // Enter the waiting queue, which is a circular doubly linked list in this case // but it could be a priority queue or any data structure. // _WaitSetLock protects the wait queue. Normally the wait queue is accessed only // by the the owner of the monitor *except* in the case where park() // returns because of a timeout of interrupt. Contention is exceptionally rare // so we use a simple spin-lock instead of a heavier-weight blocking lock. Thread::SpinAcquire (&_WaitSetLock, "WaitSet - add") ; AddWaiter (&node) ; Thread::SpinRelease (&_WaitSetLock) ; .... int ret = OS_OK ; int WasNotified = 0 ; { // State transition wrappers OSThread* osthread = Self->osthread(); OSThreadWaitState osts(osthread, true); { ThreadBlockInVM tbivm(jt); // 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) { if (millis <= 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....}
这段函数相当的长,为了从宏观上理解流程,我们删去了很多中间部分,重点在 ObjectWaiter node(Self); Self 是Thread 对象,将Thread 和 ObjectWaiter 关联起来,
ObjectMonitor::AddWaiter() 将 node加入到 ObjectWaiter 的_WaitSet 中
Self->_ParkEvent->park () ;
将会调用
void os::PlatformEvent::park() { // AKA "down()" // Invariant: Only the thread associated with the Event/PlatformEvent // may call park(). // TODO: assert that _Assoc != NULL or _Assoc == Self int v ; for (;;) { v = _Event ; if (Atomic::cmpxchg (v-1, &_Event, v) == v) break ; } guarantee (v >= 0, "invariant") ; if (v == 0) { // Do this the hard way by blocking ... int status = pthread_mutex_lock(_mutex); assert_status(status == 0, status, "mutex_lock"); guarantee (_nParked == 0, "invariant") ; ++ _nParked ; while (_Event < 0) { status = pthread_cond_wait(_cond, _mutex); // for some reason, under 2.7 lwp_cond_wait() may return ETIME ... // Treat this the same as if the wait was interrupted if (status == ETIME) { status = EINTR; } assert_status(status == 0 || status == EINTR, status, "cond_wait"); } -- _nParked ; // In theory we could move the ST of 0 into _Event past the unlock(), // but then we'd need a MEMBAR after the ST. _Event = 0 ; status = pthread_mutex_unlock(_mutex); assert_status(status == 0, status, "mutex_unlock"); } guarantee (_Event >= 0, "invariant") ;}从代码中可以看出线程将进入等待中
本质结论:
1.sleep() 只是主动调用schedule() ,放弃CPU时间片
2.wait() 线程并没有主动放弃CPU, 在linux 下 调用 pthread_cond_wait() 等待条件满足再次进入Runnning 状态
本文从宏观上分析了sleep() 和wait()的 区别,中间还有很多的细节,值得去学习,后续将继续深化。
0 0
- 从源码角度分析java 的 sleep()和wait()究竟有什么区别?
- Java sleep() 和 wait() 有什么区别
- Java sleep()和wait()有什么区别
- Java多线程中sleep()和wait()有什么区别
- Java多线程中sleep()和wait()有什么区别
- JAVA中sleep() 和 wait() 有什么区别?
- Java中sleep和wait有什么区别?
- sleep和wait有什么区别
- sleep() 和 wait() 有什么区别
- sleep和wait有什么区别
- sleep() 和 wait() 有什么区别?
- sleep() 和 wait() 有什么区别?
- sleep和wait有什么区别。
- sleep() 和 wait() 有什么区别?
- sleep和wait有什么区别
- sleep和wait有什么区别
- sleep和wait有什么区别
- sleep() 和 wait() 有什么区别?
- RESTful服务最佳实践——(十一)
- 关于安卓导航栏
- svm随机次梯度下降算法-pegasos
- 最大公约数和真分数
- 异步任务神器 Celery
- 从源码角度分析java 的 sleep()和wait()究竟有什么区别?
- NoSQL 发展,数据库发展MySQL瓶颈
- Linux命令之vi(vim类似)
- FZU2089-数字游戏
- 记录几个非常实用的js函数
- Property or field 'siteUrl' cannot be found on object of type 'xx'
- java在oj中的输入
- 用户登录记住密码案例
- 基于hunt工具的TCP会话劫持攻击实验