java Thread.yield()方法探究

Thread.yield()方法大家都知道是让当前线程让出它的cup占用,然而还是有些细节问题值得我们去探究。

1.本地方法,C++ yield()函数的映射?

这个方法在Thread类的jdk源码里面是这样的:

public static native void yield();

这是一个本地方法,因为让出当前线程的CPU占用是一个非常底层的操作,这不是java语言本身所可以做到的。

另外学过C++的都知道,C++11的标准库里面就有std::this_thread::yield()函数,jvm本身就是用C++写的,所以java的Thread.yield()极有可能就是映射的这个函数,对C++的std::this_thread::yield()函数进行进一步的封装。对于这一点的佐证是,cppreference文档上面对yield()函数的说明与JDK文档中对Thread.yield()方法的说明如出一辙。

2.线程使用yield()让出CPU占用后,它会参与下一次的调度吗?

我的回答是:不能确定

你可能在网上看到一些人说,某个线程使用yield()方法让出CPU占用后,它还会参与下一次的调度。但是这种说法其实是不准确的。

在早期的版本中,jvm自己内建调度器,有统一的调度模型,但是在后来的版本中,jvm的线程调度就是依赖于底层操作系统的调度器了,因为现代操作的调度器已经很完善了,没有必要再内建调度器,带来更多的系统开销。

所以,决定(使用yield()方法让出CPU占用的)线程是否参与下一次调度的是操作系统的调度算法,这不是java语言甚至是jvm平台所能决定的。

前面提到Thread.yield()方法极有可能是C++ yield()函数的映射,cppreference文档上面对yield()函数的说明是这样的:
在这里插入图片描述这足以说明一些问题了。

所以当我们讨论 线程使用yield()让出CPU占用后,它会参与下一次的调度吗? 这个问题时,应该去看看自己的操作系统的调度算法对这个问题的处理。

3.问题2的更进一步:操作系统是如何处理问题2的

经过问题2的研究,我们知道问题2的答案实际上是要看自己的操作系统是如何处理的。

前面的cppreference文档举了一个 先进先出实时调度器( Linux 的 SCHED_FIFO ) 的例子。操作系统的调度算法、调度策略一般都非常复杂,不同操作系统也会有不同的调度算法和策略。但是结合cppreference文档举的例子,我们可以得知:

操作系统应该会保证:某线程使用yield()方法让出CPU时间片后,调度器会尽量不选择这个线程下一次运行。

这也就是说,某线程使用yield()方法让出CPU时间片后,这个线程可能不会再参与下一次的调度,即使参与下一次的调度了,调度器也会优先让其他线程运行

我可以肯定的告诉大家,上面所说的这一点应该是能确定的。(要知道搞出操作系统的那堆人可都是天才,不可能在设计调度器的时候没有考虑到这个问题,而且即使当时忽略了这个问题,操作系统经过这么多年的发展,这个问题肯定早就被考虑到了。)

4.结语

上面提到 jvm的线程调度是依赖于底层操作系统的,但也并非就是绝对完全用操作系统的调度器,这期间还有什么弯弯绕绕我们就不得而知了。jvm的实现也是多种多样,oracle只是给了个规范,具体咋实现还是看的各家意愿,Thread.yield()方法是C++ yield()函数的映射也只是我们的一个猜想。

所以,在线程使用yield()让出CPU占用后,它是否会参与下一次的调度的这个问题上,jvm也可能插了一脚。但是我们可以唯一肯定的一件事是:

操作系统和 jvm应该会保证:某线程使用yield()方法让出CPU时间片后,调度器会尽量不选择这个线程下一次运行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值