Thread.yield原理分析

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占有权。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章