kotlin - 使用 Kotlin 的 map 委托(delegate)同步对可变字段的访问

标签 kotlin delegates thread-safety synchronized

此实现是否可以安全地同步对公共(public)字段/属性的访问?

class Attributes(
    private val attrsMap: MutableMap<String, Any?> = Collections.synchronizedMap(HashMap())
) {

    var attr1: Long? by attrsMap
    var attr2: String? by attrsMap
    var attr3: Date? by attrsMap
    var attr4: Any? = null
    ...
}

最佳答案

大多。
因为底层映射只能通过同步包装器访问,所以您不会遇到由单个调用引起的任何问题,例如同时获取和/或放置(这是竞争条件的主要原因):只有一个线程可以进行这样的调用,Java 内存模型确保结果对所有线程可见。
您可能会遇到涉及一系列调用的竞争条件,例如遍历 map ,或 check followed by a modify ,如果 map 可以在两者之间进行修改。 (即使在单个线程上也可能发生这种问题。)但是只要您的其他类(class)避免此类序列,并且没有泄漏对 map 的引用,您就安全了。
因为类型 Long , String , 和 Date是不可变的,修改其内容不会有任何问题。
这是 Any 的一个问题。不过参数。如果它存储例如一个 StringBuilder,一个线程可能正在修改其内容,而另一个线程正在访问它,这会产生可笑的后果。不过,在包装类中您无能为力。
顺便说一句,您可以使用 ConcurrentHashMap ,而不是使用同步包装器。 ,这将在大多数情况下避免同步(以更多内存为代价)。它还提供了许多可以替换调用序列的方法,例如 getOrPut() ;它是编写高性能多线程代码的真正强大工具。

关于kotlin - 使用 Kotlin 的 map 委托(delegate)同步对可变字段的访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64063001/

相关文章:

c# - Func<T> Inkover 错误无法从用法中推断出来。尝试明确指定类型参数

c# - 在 C# 中访问委托(delegate)中的类成员

java - 线程 - 为什么必须在 try 和 finally 之后使用 Lock

ios - MagicalRecord 不能在后台线程中工作吗?

java - 内联类在 openJdk 上生成奇怪的名字

java - 我是唯一一个 IDEA 的自动导入在 Kotlin 中不起作用的人吗?

Kotlin 协程 - 使用协程作用域/上下文的不同选项?

android - 使用 LiveData 时,为什么要在 ViewModel 类中双重声明变量?

C# 通过 Delegate.CreateDelegate 使用具有值类型的属性

java - 如何让构造函数安全?