-
Notifications
You must be signed in to change notification settings - Fork 21
Closed
Description
The ScalaDoc states that a scala.collection.concurrent.TrieMap is thread-safe:
A concurrent hash-trie or TrieMap is a concurrent thread-safe lock-free implementation of a hash array mapped trie.
But the method getOrElseUpdate
of scala.collection.mutable.MapLike is not overridden and is therefore not thread safe:
def getOrElseUpdate(key: A, op: => B): B =
get(key) match {
case Some(v) => v
case None => val d = op; this(key) = d; d
}
This issue can be recreated with the following code:
import scala.collection.concurrent.TrieMap
object TrieMapApp extends App {
object ApplyMeOnce {
var applied = false
def apply() = synchronized {
require(!applied)
applied = true
}
}
val map = TrieMap.empty[String, Unit]
val runnable = new Runnable {
def run() = {
try {
map.getOrElseUpdate("Result", ApplyMeOnce())
} catch {
case e: Exception => exception = Some(e)
}
}
}
var exception: Option[Exception] = None
while (exception == None) {
1 to 10 map { i => new Thread(runnable, i.toString) } foreach { thread => thread.start() }
println(exception)
}
println(exception)
}
Please let me know if you need more information.
As a workaround you can write:
synchronized { map.getOrElseUpdate("Result", ApplyMeOnce()) }