ConcurrentHashMap and Fibonacci Numbers - Inconsistent result
我用
当我使用像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class Test { static Map<Integer, Integer> concurrentMap = new ConcurrentHashMap<>(); public static void main(String[] args) { System.out.println("Fibonacci result for 20 is" + fibonacci(20)); } static int fibonacci(int i) { if (i == 0) return i; if (i == 1) return 1; return concurrentMap.computeIfAbsent(i, (key) -> { System.out.println("Value is" + key); return fibonacci(i - 2) + fibonacci(i - 1); }); } } |
有人能告诉我为什么它永远被卡住了吗?
你陷入了僵局。
Concurrenthashmap上的
我会重新考虑你决定在这里使用
我进行了线程转储,我们可以看到锁为0x00000076b70bba0的线程导致了死锁问题。
如果我错了,请纠正我。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | main - priority:5 - threadId:0x00000000021af000 - nativeId:0x2798 - state:RUNNABLE stackTrace: java.lang.Thread.State: RUNNABLE at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1674) - locked <0x000000076b70bba0> (a java.util.concurrent.ConcurrentHashMap$ReservationNode) at Test.fibonacci(Test.java:18) at Test.lambda$0(Test.java:20) at Test$$Lambda$1/834600351.apply(Unknown Source) at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) - locked <0x000000076b70c720> (a java.util.concurrent.ConcurrentHashMap$ReservationNode) at Test.fibonacci(Test.java:18) at Test.lambda$0(Test.java:20) at Test$$Lambda$1/834600351.apply(Unknown Source) at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) - locked <0x000000076b70c5c0> (a java.util.concurrent.ConcurrentHashMap$ReservationNode) at Test.fibonacci(Test.java:18) at Test.lambda$0(Test.java:20) at Test$$Lambda$1/834600351.apply(Unknown Source) at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) - locked <0x000000076b70c460> (a java.util.concurrent.ConcurrentHashMap$ReservationNode) at Test.fibonacci(Test.java:18) at Test.lambda$0(Test.java:20) at Test$$Lambda$1/834600351.apply(Unknown Source) at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) - locked <0x000000076b70c300> (a java.util.concurrent.ConcurrentHashMap$ReservationNode) at Test.fibonacci(Test.java:18) at Test.lambda$0(Test.java:20) at Test$$Lambda$1/834600351.apply(Unknown Source) at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) - locked <0x000000076b70c1a0> (a java.util.concurrent.ConcurrentHashMap$ReservationNode) at Test.fibonacci(Test.java:18) at Test.lambda$0(Test.java:20) at Test$$Lambda$1/834600351.apply(Unknown Source) at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) - locked <0x000000076b70c040> (a java.util.concurrent.ConcurrentHashMap$ReservationNode) at Test.fibonacci(Test.java:18) at Test.lambda$0(Test.java:20) at Test$$Lambda$1/834600351.apply(Unknown Source) at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) - locked <0x000000076b70bee0> (a java.util.concurrent.ConcurrentHashMap$ReservationNode) at Test.fibonacci(Test.java:18) at Test.lambda$0(Test.java:20) at Test$$Lambda$1/834600351.apply(Unknown Source) at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) - locked <0x000000076b70bba0> (a java.util.concurrent.ConcurrentHashMap$ReservationNode) at Test.fibonacci(Test.java:18) at Test.main(Test.java:8) Locked ownable synchronizers: - None |
这种计算斐波纳契数的递归方法具有指数复杂性。通过缓存,可以将其减少到线性,或者可以使用简单的循环而不是递归来获得线性算法。
我想知道为什么要使用ConcurrentHashMap进行缓存。我将使用简单的映射或数组进行缓存。
当值稀疏时,映射相对于数组有优势,但当您有数字序列时,可以使用简单数组。
根据Oracle文件
Some attempted update operations on this map by other threads may be blocked while computation is in progress, so the computation should be short and simple, and must not attempt to update any other mappings of this map
正如JoeC在最前面的答案中所说的,
使用
如果您仍然希望在应用程序中继续使用
1 |
可计算出费波纳契级数,包括
根据DOC,
ConcurrentHashMap()
Creates a new, empty map with the default initial table size (16).
不过,我希望在这方面有所不同,因为我注意到默认大小要小得多。原因是当你从