7

可能重复:
多线程 Java 应用程序会很好地利用多核机器吗?

我有一个像这样在我的双核机器上运行的简单的 Java 线程(Windows XP 32 位环境)

public static void main(String[] strs) {

    long j  = 0;
    for(long i = 0; i<Long.MAX_VALUE; i++)
        j++;

    System.out.println(j);
    }

我的期望是它会坚持使用单个 CPU 来充分利用高速缓存(因为在循环中我们一直使用局部变量 j 进行操作,因此一个 CPU 利用率将是 100%,而另一个 CPU 利用率几乎是空闲的。令我惊讶的是,线程启动后两个 CPU 的利用率都在 40%~60% 左右,一个 CPU 的利用率略高于另一个。

我的问题是,当检测到不平衡时,是否有任何操作系统负载平衡机制启动?在我的情况下,Windows 操作系统是否有可能发现一个 CPU 接近 100% 而另一个几乎空闲,因此它会定期将线程重新调度到另一个 CPU?

在此处输入图像描述

#EDIT1 我找到了一个可能的解释: http ://siber.cankaya.edu.tr/ozdogan/OperatingSystems/ceng328/node130.html

4

3 回答 3

3

当操作系统执行线程时,它会运行每个线程一段时间(比如 10-20ms),然后保存线程的状态,并寻找其他线程运行。

现在,尽管您从 CPU 利用率图表中可能会想到什么,但操作系统实际上运行的线程比您程序中的线程多得多。有运行 UI 循环的线程、等待 I/O 的线程、运行后台服务的线程等。大多数线程将大部分时间花在阻塞等待某事上。

我谈论这个的原因是为了解释从操作系统的角度来看,情况比看起来更复杂。有一大堆线程在做一大堆事情,操作系统正试图在它们之间切换。假设你想实现一个启发式方法,如果一个线程最后一次用完了它的整个量程,那么操作系统会努力将它调度到同一个核心。操作系统需要跟踪和考虑更多的信息,优化的成功可能取决于很多难以预测的因素。

此外,将线程关联到内核的好处在实践中通常可以忽略不计,因此操作系统不会尝试自动执行此操作。相反,它们公开了一项功能,允许开发人员明确表示特定线程应与内核关联,然后操作系统将尊重该决定。

这似乎是一个合理的权衡:如果您的线程在关联到内核时性能更好,只需要求操作系统执行此操作即可。但是,操作系统不会费心为您解决问题。

于 2012-03-01T08:14:49.133 回答
1

正如您所提到的,操作系统会反弹线程。以下本机代码也按照您的描述执行。

int main( int argc, char** argv )
{
    while( true );
    return 0;
}

如果您查看该过程,它始终保持在 25%(使用四核),但 Windows 7 的资源监视器显示 4 个内核中没有一个处于恒定 100%,即使核心 0 的使用率高于其他。

cpu 可能会在内核之间共享缓存,所以这种行为并不意味着缓存没有被使用。

于 2012-03-01T03:00:18.573 回答