28

I need a mutable thread safe Map and a mutable thread safe List in Scala. I know that the immutable collections are thread safe by default. But, I need to update my collections very often because of which I couldn't use immutable. Also I need my threadsafe mutable Map to maintain the insertion order.

Right now am using the map below

val map = scala.collection.mutable.LinkedHashMap[String,Any]()

This map maintains the insertion order and is mutable. How do I make it thread safe?

om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
yAsH
  • 3,367
  • 8
  • 36
  • 67
  • possible duplicate of [Thread safe map which preserves the insertion order](http://stackoverflow.com/questions/17540467/thread-safe-map-which-preserves-the-insertion-order) – 4lex1v Jul 09 '13 at 07:11
  • 1
    @AlexIv not a duplicate in complete sense -- rahul asks about List too – om-nom-nom Jul 09 '13 at 16:10
  • @om-nom-nom anyway it could be modified, but create a new question is excess – 4lex1v Jul 09 '13 at 16:17

3 Answers3

44

Fast hint for those coming to this in 2018 or later:

import java.util.concurrent.ConcurrentHashMap

val m: ConcurrentHashMap[String,MyClass] = new ConcurrentHashMap
akauppi
  • 17,018
  • 15
  • 95
  • 120
21
  1. You're duplicating topics....
  2. As was mentioned by AlexIv in his answer, there's a trait you can mix in if you want thread safety. There's another way though:

    val synchronizedMap = new scala.collection.mutable.LinkedHashMap[String, Any]() with scala.collection.mutable.SynchronizedMap[String, Any]
    

That should give you the map with synchronization on each access. Easy, but might not meet the performance requirements. If so, it would be probably easier to create a custom class extending the LinkedHashMap, mixing in the concurrent.Map trait (as was suggested) and provide the implementation of relevant methods, i.e: putIfAbsent, remove replace (2 overloads).

Community
  • 1
  • 1
Patryk Ćwiek
  • 14,078
  • 3
  • 55
  • 76
  • 21
    If you can stand a bit more work, use the `synchronized` method on the mutable collection directly where you need thread safety. It'll save you the performance hit that this mixin brings. E.g. `someMap.synchronized { someMap += ("someKey", "anyValue") }` – tysonjh Mar 06 '14 at 14:32
  • 12
    For anyone new viewing this, the SynchronizedMap trait has been deprecated as not safe enough. Recommends using Java thread safe collections. – Patrick White Aug 20 '15 at 01:20
  • 1
    It's a compiler warning when you build after mixing in this trait - not sure about a link – Patrick White Oct 10 '15 at 19:34
  • 4
    @Gepp: http://www.scala-lang.org/api/2.12.3/scala/collection/mutable/SynchronizedMap.html: "(Since version 2.11.0) Synchronization via traits is deprecated as it is inherently unreliable. Consider `java.util.concurrent.ConcurrentHashMap` as an alternative." – Jeremy Rodi Nov 08 '17 at 22:13
  • 2
    TrieMap is mutable, thread-safe, lock-free, and is not deprecated – ianpojman Nov 05 '20 at 23:05
  • > @deprecated("Synchronization via traits is deprecated as it is inherently unreliable. Consider java.util.concurrent.ConcurrentHashMap as an alternative.", "2.11.0") trait SynchronizedMap[A, B] extends Map[A, B] { it's deprecated already. – linehrr Oct 04 '22 at 17:47
0

To elaborate on the comment for a Map you can use

import scala.collection.concurrent.TrieMap

Is not deprecated and is mutable and thread-safe.

It should drop in for your scala.collection.mutable.LinkedHashMap as they share the same interface of scala.collection.mutable.MapLike and scala.collection.mutable.Map

Sadly I don't know about the List

haagmm
  • 583
  • 6
  • 10