Linux JVM实际上是否实现了线程优先级?

写了一个快速的Java proggy以产生每个优先级的10个线程并计算pi(4 * atan(1)方法),每个BigDecimals 500,000次,加入每个线程并报告run方法的运行时间。 是的,可能不是最好的例子,但保持基本。

我知道Bug4813310

在C中做起来并非易事,但是我们可以假设在Linux JVM上永远不会设置原生优先级吗?

$uname -r && grep bogomips /proc/cpuinfo 2.4.33.3 bogomips : 4312.26 $java -version 2>&1 |head -1 Java version "1.6.0_01" $javac T.java && java -Xmx32m -XX:+UseThreadPriorities T 1:3112 2:2636 3:2662 4:3118 5:2870 6:3319 7:3412 8:3304 9:3299 10:3069 

看起来没有人会期待的偏差! 那是在一台小型虚拟Linux机器上。 也许只是Sun的? 我们将尝试IBM J9 VM:

 1:4091 2:4142 3:3957 4:3905 5:3984 6:3985 7:4130 8:4055 9:3752 10:4071 

相比之下,总数看起来相当不错,但从线程优先级的角度来看,数字没有规模。

让我们尝试在2.6内核上使用较旧的Sun JVM进行500k迭代,其中一个常常加载的平均负载很少低于7:

 $uname -r && grep bogomips /proc/cpuinfo 2.6.9-67.ELsmp bogomips : 3992.93 bogomips : 3990.00 $java -version 2>&1 |head -1 java version "1.4.2_14" $javac T.java && java -Xmx32m -XX:+UseThreadPriorities T 1:63200 2:64388 3:62532 4:58529 5:62292 6:64872 7:64885 8:64584 9:61653 10:61575 

让我们在2.6内核上尝试使用IBM的J9,因为更大的系统我会将迭代次数增加到2,000,000。

 $uname -r && grep bogomips /proc/cpuinfo 2.6.9-78.ELsmp bogomips : 5989.03 bogomips : 5985.03 bogomips : 5985.01 bogomips : 5985.02 bogomips : 5984.99 bogomips : 5985.02 bogomips : 5984.99 bogomips : 5985.02 $java -Xmx32m T # this is the IBM J9 1:1718 2:1569 3:1989 4:1897 5:1839 6:1688 7:1634 8:1552 9:2027 10:1522 

有些好的时候,但仍然没有明显的线程/流程优先级。

我们来试试Windows吧。 我知道Windows有一个相当激进的线程优先级方案。 任何高于正常情况的事物都会消耗更多。 因此,让我们在每个线程中移动到900,000次迭代:

 C:\>java -version java version "1.6.0_11" C:\>java -Xmx32m T 1:12578 2:12625 3:11469 4:11453 5:10781 6:8937 7:10516 8:8406 9:9953 10:7391 

我们正在寻找什么,不是吗?

那么Linux JVM显然没有线程优先级? 我知道你不能真正降低C级的低级别,但我认为JVM工程师会想出如何保持一个低级别的调度程序。

好吧,让我们来看看来源 :

第2947行:

 //////////////////////////////////////////////////////////////////////////////// // thread priority support // Note: Normal Linux applications are run with SCHED_OTHER policy. SCHED_OTHER // only supports dynamic priority, static priority must be zero. For real-time // applications, Linux supports SCHED_RR which allows static priority (1-99). // However, for large multi-threaded applications, SCHED_RR is not only slower // than SCHED_OTHER, but also very unstable (my volano tests hang hard 4 out // of 5 runs - Sep 2005). // // The following code actually changes the niceness of kernel-thread/LWP. It // has an assumption that setpriority() only modifies one kernel-thread/LWP, // not the entire user process, and user level threads are 1:1 mapped to kernel // threads. It has always been the case, but could change in the future. For // this reason, the code should not be used as default (ThreadPriorityPolicy=0). // It is only used when ThreadPriorityPolicy=1 and requires root privilege. 

第2982行:

  static int prio_init() { if (ThreadPriorityPolicy == 1) { // Only root can raise thread priority. Don't allow ThreadPriorityPolicy=1 // if effective uid is not root. Perhaps, a more elegant way of doing // this is to test CAP_SYS_NICE capability, but that will require libcap.so if (geteuid() != 0) { if (!FLAG_IS_DEFAULT(ThreadPriorityPolicy)) { warning("-XX:ThreadPriorityPolicy requires root privilege on Linux"); } ThreadPriorityPolicy = 0; } } return 0; } 

第2997行:

 OSReturn os::set_native_priority(Thread* thread, int newpri) { if ( !UseThreadPriorities || ThreadPriorityPolicy == 0 ) return OS_OK; int ret = setpriority(PRIO_PROCESS, thread->osthread()->thread_id(), newpri); return (ret == 0) ? OS_OK : OS_ERR; } 

所以! 至少在Sun Java上,在Linux上,你不会看到线程优先级,除非你已经完成-XX:ThreadPriorityPolicy并且似乎需要root。

默认的Linux线程调度程序策略SCHED_OTHER不支持优先级。 或者更确切地说,它支持具有一个值的优先级设置:0。另一个所谓的“实时”策略SCHED_FIFO和SCHED_RR支持更高的优先级,但仅适用于具有超级用户权限的进程。

这里只是一个黑暗的镜头,但是在JVM中没有优先级的线程需要能够调整操作系统线程的优先级吗?

Linux(以及任何类Unix操作系统)限制了为root提供进程更高优先级的能力。 我认为线程会有类似的限制。