我有 Scala 的代码

class MyClass {
  private val myData: Map[String, MyClass2] = new HashMap[String, MyClass2]()

  def someMethod = {
      synchronized(myData) {
        val id = getSomeId
        if (myData.containsKey(id)) myData = myData.remove(id)
        else Log.d("123", "Not found!")
      }
  }

  def getSomeId = //....
}

我想知道,是否有可能在不使用 synchronized 并且不涉及其他一些库(例如 Akka 或任何其他 (类)甚至内置在 Java 或 Scala 中)的情况下保持此代码线程安全?

理想情况下,我只想通过使用不变性的概念(Java 中的 final,如果你愿意)来使线程安全。

更新 :
class MyClass(myData: Map[String, MyClass2] = new HashMap[String, MyClass2]()) {

  def someMethod = {
      synchronized(myData) {
        val id = getSomeId
        if (myData.containsKey(id)) new MyClass(myData.remove(id))
        else {
           Log.d("123", "Not found!")
           this
         }
      }
  }

  def getSomeId = //....
}

最佳答案

只有使 MyClass 也是不可变的(并且让它也只使用不可变的数据结构),才能解决不可变性的问题。原因很简单: 如果 MyClass 是可变的,那么你必须通过并发线程同步修改。

这需要不同的设计 - 每个导致 MyClass 实例“更改”的操作都将返回一个(可能)修改过的实例。

import collection.immutable._

class MyClass2 {
  // ...
}

// We can make the default constructor private, if we want to manage the
// map ourselves instead of allowing users to pass arbitrary maps
// (depends on your use case):
class MyClass private (val myData: Map[String,MyClass2]) {
  // A public constructor:
  def this() = this(new HashMap[String,MyClass2]())

  def someMethod(id: String): MyClass = {
    if (myData.contains(id))
      new MyClass(myData - id) // create a new, updated instance
    else {
      println("Not found: " + id)
      this // no modification, we can return the current
            // unmodified instance
    }
  }

  // other methods for adding something to the map
  // ...
}

10-08 02:23