Java ConcurrentHashMap和Fibonacci数-结果不一致

Java ConcurrentHashMap和Fibonacci数-结果不一致,java,fibonacci,concurrenthashmap,Java,Fibonacci,Concurrenthashmap,我用ConcurrentHashMap和computeifassent()方法编写了一个递归计算斐波那契数的程序: 当我使用像8,9,10这样的小值时,程序运行绝对正常,但当值从10增加到20时,程序会陷入无休止的循环中 public class Test { static Map<Integer, Integer> concurrentMap = new ConcurrentHashMap<>(); public static void main(S

我用
ConcurrentHashMap
computeifassent()方法编写了一个递归计算斐波那契数的程序:

当我使用像
8,9,10
这样的小值时,程序运行绝对正常,但当值从
10增加到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);
        });
    }
}
公共类测试{
静态映射concurrentMap=新的ConcurrentHashMap();
公共静态void main(字符串[]args){
System.out.println(“20的斐波那契结果是”+斐波那契(20));
}
静态整数fibonacci(整数i){
如果(i==0)
返回i;
如果(i==1)
返回1;
返回concurrentMap.ComputeFabSent(i,(键)->{
System.out.println(“值为”+键);
返回斐波那契(i-2)+斐波那契(i-1);
});
}
}

有人能告诉我为什么它会永远被卡住吗?

你正陷入僵局

ConcurrentHashMap上的
computeIfAbsent
将锁定相应密钥所在的存储桶。如果您试图计算的Fibonacci值高于映射中的存储桶数,则递归调用将尝试锁定已在调用堆栈中进一步锁定的存储桶。但当然,在所有递归调用完成之前,无法释放该锁。因此,你的僵局


我将重新考虑您在此处使用ConcurrentHashMap的决定。

这种计算fibonaci数的递归方法具有指数复杂性。通过缓存,您可以将其还原为线性,或者可以使用简单循环而不是递归来获得线性算法

我想知道你为什么使用ConcurrenthashMap进行缓存。我将使用简单映射或数组进行缓存


当值是稀疏的时,Maps相对于数组有优势,但当您有数字序列时,您可以使用简单数组。

我进行了线程转储,我们可以看到带锁的线程0x000000076b70bba0导致死锁问题

如果我错了,请纠正我

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
main-优先级:5-线程ID:0x00000000021af000-本地ID:0x2798-状态:可运行
堆栈跟踪:
java.lang.Thread.State:可运行
位于java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1674)
-锁定(java.util.concurrent.ConcurrentHashMap$ReservationNode)
at Test.fibonacci(Test.java:18)
在Test.lambda$0(Test.java:20)
测试时$$Lambda$1/834600351。应用(未知来源)
位于java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
-锁定(java.util.concurrent.ConcurrentHashMap$ReservationNode)
at Test.fibonacci(Test.java:18)
在Test.lambda$0(Test.java:20)
测试时$$Lambda$1/834600351。应用(未知来源)
位于java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
-锁定(java.util.concurrent.ConcurrentHashMap$ReservationNode)
at Test.fibonacci(Test.java:18)
在Test.lambda$0(Test.java:20)
测试时$$Lambda$1/834600351。应用(未知来源)
位于java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
-锁定(java.util.concurrent.ConcurrentHashMap$ReservationNode)
at Test.fibonacci(Test.java:18)
在Test.lambda$0(Test.java:20)
测试时$$Lambda$1/834600351。应用(未知来源)
位于java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
-锁定(java.util.concurrent.ConcurrentHashMap$ReservationNode)
at Test.fibonacci(Test.java:18)
在Test.lambda$0(Test.java:20)
测试时$$Lambda$1/834600351。应用(未知来源)
位于java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
-锁定(java.util.concurrent.ConcurrentHashMap$ReservationNode)
at Test.fibonacci(Test.java:18)
在Test.lambda$0(Test.java:20)
测试时$$Lambda$1/834600351。应用(未知来源)
位于java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
-锁定(java.util.concurrent.ConcurrentHashMap$ReservationNode)
at Test.fibonacci(Test.java:18)
在Test.lambda$0(Test.java:20)
测试时$$Lambda$1/834600351。应用(未知来源)
位于java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
-锁定(java.util.concurrent.ConcurrentHashMap$ReservationNode)
at Test.fibonacci(Test.java:18)
在Test.lambda$0(Test.java:20)
测试时$$Lambda$1/834600351。应用(未知来源)
位于java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
-锁定(java.util.concurrent.ConcurrentHashMap$ReservationNode)
at Test.fibonacci(Test.java:18)
at Test.main(Test.java:8)
锁定可拥有的同步器:
-没有
根据

在计算过程中,其他线程在此映射上尝试的某些更新操作可能会被阻止,因此计算应该简短,并且不得尝试更新此映射的任何其他映射

正如Joe C在最上面的答案中正确地指出的那样,
ConcurrentHashMap
的默认初始化在实例化时分配了少量的bucket

使用
ConcurrentHashMap
的目的是允许多个线程同时修改映射,而无需阻塞它们()


如果您仍然想继续为您的应用程序使用
ConcurrentHashMap
,那么我建议在创建过程中增加initialCapacity

static Map<Integer, Integer> concurrentMap = new ConcurrentHashMap<>(11);
静态映射concurrentMap=新的ConcurrentHashMap(11);
可以计算斐波那契数列,最多25个


根据文件,

ConcurrentHashMap()
使用默认初始表大小(16)创建新的空映射

然而,我不同意你的看法