Ошибка Scala с неизменяемой картой в параллельной программе? - PullRequest
5 голосов
/ 18 декабря 2009

Я написал игрока Монте-Карло для настольной игры 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)

Я использую только неизменные Карты, поэтому мне интересно, вызвано ли это ошибкой в ​​моем собственном коде или, возможно, ошибкой в ​​библиотеке scala. Глядя на трассировку, вы видите, что есть вызовы к изменяемой HashTable дальше по стеку. Может быть, это вызывает проблемы с параллелизмом?

Код внутри моей программы, где происходит исключение, - это просто добавление еще одной коллекции в неизменяемую карту:

myMap ++ (someInteger -> aValue)

Edit: Та же программа без параллелизма работает без сбоев.

Ответы [ 2 ]

2 голосов
/ 22 декабря 2009

Я отправил отчет об ошибке для библиотеки Scala. Оказывается, это известная проблема. Реализация HashMap (которая используется как стандартный тип Map в Scala) не подходит для параллельных программ, поскольку за кулисами используются изменяемые типы. Это также можно наблюдать в трассировке стека. Люди Scala надеются заменить реализацию в 2.8.

В качестве обходного пути предлагается использовать TreeHashMap, который действительно неизменен. Я сделал это и могу подтвердить, что это работает.

Ссылка на оригинальный отчет об ошибке

0 голосов
/ 18 декабря 2009

Это, безусловно, может вызвать проблемы с параллелизмом. Смешайте карту с SynchronizedMap, как минимум.

Но учтите, что это не дает вам никаких транзакционных гарантий. Это просто гарантирует, что Карта не сломается у вас под ногами.

...