【发布时间】:2014-01-15 12:46:47
【问题描述】:
我在一台四核 cpu 的机器上运行 Ubuntu。我编写了一些测试 Java 代码,它们生成给定数量的进程,这些进程在运行时为给定的迭代次数增加一个 volatile 变量。
我希望运行时间不会显着增加,而线程数小于或等于内核数,即 4。事实上,这些是我从 UNIX @987654321 使用“实时”获得的时间@命令:
1 个线程:1.005 秒
2 个线程:1.018 秒
3 个线程:1.528 秒
4 个线程:1.982 秒
5 个线程:2.479 秒
6 线程:2.934 秒
7 线程:3.356 秒
8 个线程:3.793 秒
这表明添加一个额外的线程并没有像预期的那样增加时间,但是随着 3 和 4 个线程,时间确实增加。
起初我认为这可能是因为操作系统阻止了 JVM 使用所有内核,但我运行了top,它清楚地显示了 3 个线程,3 个内核以 ~100% 的速度运行,并且4个线程,4个核心被刷爆。
我的问题是:为什么在 3/4 CPU 上运行的代码的速度与在 1/2 上运行时的速度不同?因为它在所有内核上并行运行。
这是我的主要参考方法:
class Example implements Runnable {
// using this so the compiler does not optimise the computation away
volatile int temp;
void delay(int arg) {
for (int i = 0; i < arg; i++) {
for (int j = 0; j < 1000000; j++) {
this.temp += i + j;
}
}
}
int arg;
int result;
Example(int arg) {
this.arg = arg;
}
public void run() {
delay(arg);
result = 42;
}
public static void main(String args[]) {
// Get the number of threads (the command line arg)
int numThreads = 1;
if (args.length > 0) {
try {
numThreads = Integer.parseInt(args[0]);
} catch (NumberFormatException nfe) {
System.out.println("First arg must be the number of threads!");
}
}
// Start up the threads
Thread[] threadList = new Thread[numThreads];
Example[] exampleList = new Example[numThreads];
for (int i = 0; i < numThreads; i++) {
exampleList[i] = new Example(1000);
threadList[i] = new Thread(exampleList[i]);
threadList[i].start();
}
// wait for the threads to finish
for (int i = 0; i < numThreads; i++) {
try {
threadList[i].join();
System.out.println("Joined with thread, ret=" + exampleList[i].result);
} catch (InterruptedException ie) {
System.out.println("Caught " + ie);
}
}
}
}
【问题讨论】:
-
这是一个有趣的问题,请发布您的
Example来源。 -
我想其中一个线程也正在运行 JVM,然后生成了用于运行此代码的主线程。
-
您的 cpu 是否有 4 个物理核心,或者它是否具有 2 个物理核心和 2 个逻辑核心的超线程?
-
@AndreyChaschev 编辑成问题。
-
试着让
volatile离开你的脸——删除它并使用其他机制来确保循环不会被优化——在最后打印temp或其他东西。volatile具有许多特定于 cpu 且跨线程有效的副作用。
标签: java multithreading concurrency cpu-usage multicore