Jus*_*guy 6 java static multithreading synchronized
我正在尝试了解线程和同步.我做了这个测试程序:
public class Test {
static List<Thread> al = new ArrayList<>();
public static void main(String[] args) throws IOException, InterruptedException {
long startTime = System.currentTimeMillis();
al.add(new Thread(() -> fib1(47)));
al.add(new Thread(() -> fib2(47)));
for (Thread t : al)
t.start();
for (Thread t: al)
t.join();
long totalTime = System.currentTimeMillis() - startTime;
System.out.println(totalTime);
}
public static synchronized int fib1(int x) {
return x <= 2 ? 1 : fib1(x-2) + fib1(x-1);
}
public static synchronized int fib2(int x) {
return x <= 2 ? 1 : fib2(x-2) + fib2(x-1);
}
}
Run Code Online (Sandbox Code Playgroud)
这个程序大约需要273秒才能完成,但是如果我删除了synchronized它,它会在7秒内完成.是什么导致这种巨大的差异
编辑:我知道我正在使用一种非常慢的算法来计算斐波纳契数.而且我也知道线程不共享资源,因此这些方法不需要同步.然而,这只是一个测试程序,我试图弄清楚如何synchronized工作,我故意选择一个慢速算法,所以我可以测量所用的时间,以毫秒为单位.
你的程序并没有卡住——只是速度非常慢。这是由于两个原因:
1. 算法复杂度
正如其他人和您自己所提到的,计算斐波那契数的方式非常慢,因为它一遍又一遍地计算相同的值。使用较小的输入会将运行时间降低到合理的值。但这不是你的问题。
2. 同步
这会通过两种方式减慢你的程序:
首先,创建方法synchronized不是必需的,因为它们不会修改方法本身之外的任何内容。事实上,它阻止两个线程同时运行,因为这些方法static因此阻止两个线程同时位于其中任何一个线程中。因此,您的代码实际上仅使用一个线程,而不是两个线程。
还给synchronized方法增加了显着的开销,因为它需要在进入方法时获取锁 - 或者至少检查当前线程是否已经拥有锁。这些操作非常昂贵,并且每次输入其中一种方法时都必须执行这些操作。由于递归的原因,这种情况经常发生,因此对程序性能产生了极大的影响。
有趣的是,当您仅使用单个线程运行它时,即使方法是synchronized. 原因是 JVM 进行的运行时优化。如果您只使用一个线程,JVM 可以优化检查,synchronized因为不会发生冲突。synchronized这会显着减少运行时间 - 但由于从“冷代码”开始和一些剩余的运行时间检查,因此并不完全达到没有它应有的值。另一方面,当使用 2 个线程运行时,JVM 无法进行此优化,因此留下了synchronized导致代码非常慢的昂贵操作。
顺便说一句:fib1 和 fib2 相同,删除其中一个
| 归档时间: |
|
| 查看次数: |
2551 次 |
| 最近记录: |