Giả sử tôi muốn sử dụng bản đồ có thể thay đổi trong Scala để theo dõi số lần tôi đã xem một số chuỗi. Trong một bối cảnh đơn luồng, điều này rất dễ dàng:Chuyển đổi một cách an toàn giá trị trong bản đồ có thể thay đổi
import scala.collection.mutable.{ Map => MMap }
class Counter {
val counts = MMap.empty[String, Int].withDefaultValue(0)
def add(s: String): Unit = counts(s) += 1
}
Thật không may này không phải là thread-an toàn, kể từ khi get
và update
không xảy ra nguyên tử.
Concurrent maps thêm a few atomic operations API bản đồ có thể thay đổi, nhưng không phải là người tôi cần, đó sẽ giống như thế này:
def replace(k: A, f: B => B): Option[B]
Tôi biết tôi có thể sử dụng ScalaSTM 's TMap
:
import scala.concurrent.stm._
class Counter {
val counts = TMap.empty[String, Int]
def add(s: String): Unit = atomic { implicit txn =>
counts(s) = counts.get(s).getOrElse(0) + 1
}
}
Nhưng (hiện tại) đó vẫn là một sự phụ thuộc phụ. Các tùy chọn khác sẽ bao gồm các tác nhân (phụ thuộc khác), đồng bộ hóa (có khả năng kém hiệu quả hơn), hoặc atomic references (less idiomatic) của Java.
Nói chung tôi muốn tránh các bản đồ có thể thay đổi trong Scala, nhưng đôi khi tôi cần loại điều này, và gần đây nhất tôi đã sử dụng phương pháp STM (thay vì chỉ lướt ngón tay của tôi và hy vọng tôi không nhận được cắn bởi giải pháp ngây thơ).
Tôi biết có một số sự đánh đổi ở đây (phụ thuộc bổ sung so với hiệu suất so với sự rõ ràng, v.v.), nhưng có bất kỳ điều gì giống như câu trả lời "đúng" cho vấn đề này trong Scala 2.10 không?
những gì về một diễn viên Akka duy nhất ghi vào bản đồ có thể thay đổi? 'Counter.add' chỉ gửi một tin nhắn lửa và quên cho nó. Đối với lần đọc, tùy thuộc vào nhu cầu của bạn, chúng có thể xảy ra đồng thời hoặc cũng thông qua diễn viên. – gourlaysama