Thread.yield()方法的作用是暂时放弃当前线程对CPU的占用权,将它让给其它线程。他是如何实现的呢?通过看yield源码,发现其是本地方法,找到其在JVM中的源码实现如下:
JVM_ENTRY(void, JVM_Yield(JNIEnv *env, jclass threadClass))
JVMWrapper("JVM_Yield");
//判断操作系统是否允许使用Yield,默认是false
if (os::dont_yield()) return;
HOTSPOT_THREAD_YIELD();
// When ConvertYieldToSleep is off (default), this matches the classic VM use of yield.
// Critical for similar threading behaviour
//判断,根据字面意思,就是说是否允许把Yield操作转换为Sleep操作(默认是false),如果允许的,则调用操作系统的sleep方法,如果不允许,则调用操作系统的naked_yield方法。
if (ConvertYieldToSleep) {
os::sleep(thread, MinSleepInterval, false);
} else {
os::naked_yield();
}
JVM_END
从源码中可以看到,yield的实现,分为两种,如果允许把Yield操作转换为Sleep操作(默认是false),则调用操作系统的sleep方法,如果不允许,则调用操作系统的naked_yield方法。
如果调用Sleep方法,这个我们都比较熟悉了,其就是让当前线程睡眠一段时间,来实现释放CPU的占有的效果,这里睡眠时间为最小睡眠间隔,为1MS。
如果是调用naked_yield,naked_yield方法在linux中的实现如下:
void os::naked_yield() {
sched_yield();
}
其中sched_yield是操作系统的线程调度方法。
那sleep和sched_yield到底有什么区别呢?
sleep:让当前线程睡眠一段时间,睡眠期间释放CPU的占有权,时间到了之后,重新抢占CPU。
sched_yield:会让当前线程让出CPU占有权,然后把线程加入到同等优先级队列的末尾,然后让另一个级别等于或高于当前线程的线程先运行。如果没有符合条件的线程,那么这个函数将会立刻返回然后继续执行当前线程的程序。
所以,sleep,一定会释放当前线程的CPU占用权。而sched_yield,只有当有其他线程的优先级等于或者高于当前线程的情况下,才会让出CPU占有权。