Scala错误与并发程序中的不可变映射?

zig*_*tar 5 concurrency scala exception immutability

我为棋盘游戏Nine Men's Morris写了一个蒙特卡洛球员.一切都基本不变.该程序涉及许多未来(数百)和许多修改不可变的地图.有时我遇到以下异常的崩溃:

java.lang.NullPointerException
    at scala.collection.mutable.HashTable$class.elemHashCode(HashTable.scala:154)
    at scala.collection.immutable.HashMap.elemHashCode(HashMap.scala:41)
    at scala.collection.mutable.HashTable$class.findEntry(HashTable.scala:66)
    at scala.collection.immutable.HashMap.findEntry(HashMap.scala:41)
    at scala.collection.immutable.HashMap.undo$1(HashMap.scala:132)
    at scala.collection.immutable.HashMap.undo$1(HashMap.scala:130)
    at scala.collection.immutable.HashMap.makeCopy(HashMap.scala:154)
    at scala.collection.immutable.HashMap.makeCopyIfUpdated(HashMap.scala:161)
    at scala.collection.immutable.HashMap.update(HashMap.scala:66)
    at scala.collection.immutable.Map$class.$plus(Map.scala:66)
    at scala.collection.immutable.HashMap.$plus(HashMap.scala:41)
    at morris.players.MapBasedMorrisBoard.applyMove(MapBasedMorrisBoard.scala:30)
    at morris.players.MonteCarloPlayer$$anonfun$main$1$$anonfun$apply$1.apply(MonteCarloPlayer.scala:77)
    at morris.players.MonteCarloPlayer$$anonfun$main$1$$anonfun$apply$1.apply(MonteCarloPlayer.scala:77)
    at scala.actors.Futures$$anonfun$2$$anonfun$apply$1.apply(Future.scala:45)
    at scala.actors.Futures$$anonfun$2$$anonfun$apply$1.apply(Future.scala:44)
    at scala.actors.Reaction.run(Reaction.scala:78)
    at scala.actors.FJTask$Wrap.run(Unknown Source)
    at scala.actors.FJTaskRunner.scanWhileIdling(Unknown Source)
    at scala.actors.FJTaskRunner.run(Unknown Source)
Run Code Online (Sandbox Code Playgroud)

我只使用不可变映射,所以我想知道这是由我自己的代码中的错误还是scala库中的错误引起的.在查看您可以看到的跟踪时,可以在堆栈中进一步调用可变HashTable.也许这会引起并发问题?

我的程序中的代码,发生异常只是将另一个集合添加到不可变的Map:

myMap ++ (someInteger -> aValue)
Run Code Online (Sandbox Code Playgroud)

编辑:没有并发的相同程序运行完美.

zig*_*tar 2

我已经提交了 Scala 库的错误报告。事实证明这是一个已知问题。HashMap 的实现(在 Scala 中用作标准 Map 类型)不适合在并发程序中使用,因为它在幕后使用可变类型。这也可以在堆栈跟踪中观察到。Scala 人们希望在 2.8 中替换该实现。

作为解决方法,建议使用 TreeHashMap,它是真正不可变的。我已经做到了这一点并且可以确认它有效。

原始错误报告的链接