代码之家  ›  专栏  ›  技术社区  ›  ziggystar

并发程序中带有不可变映射的Scala bug?

  •  5
  • ziggystar  · 技术社区  · 15 年前

    我为九人莫里斯棋盘游戏写了一个蒙特卡洛球员。一切基本上都是不变的。该计划涉及大量的未来(数百)和大量修改不可变映射。有时我会遇到崩溃,但有以下例外:

    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)
    

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

    myMap ++ (someInteger -> aValue)
    

    编辑: 没有并发的同一个程序可以完美地运行。

    2 回复  |  直到 15 年前
        1
  •  2
  •   ziggystar    15 年前

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

    作为一种解决方法,建议使用TreeHashMap,它确实是不可变的。我已经这样做了,可以确认它是有效的。

    Link to original bug report

        2
  •  0
  •   Daniel C. Sobral    15 年前

    但请注意,这并没有给您任何事务保证。它只是确保地图不会在你脚下断裂。