与Kotlin的地图委托同步对可变字段的访问

问题描述

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

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内存模型可确保所有线程都可以看到结果。

可能具有涉及呼叫顺序的比赛条件,例如遍历地图,或者check followed by a modify(如果可以在地图中修改地图)之间。 (即使在单个线程上也可能发生这种问题。)但是,只要您班上的其余部分都避免了这样的序列,并且不泄漏对映射的引用,您就会很安全。

并且由于类型LongStringDate是不可变的,因此修改其内容不会有任何问题。

不过,该{em> 与Any参数有关。如果它存储例如一个StringBuilder,一个线程可能正在修改其内容,而另一个线程正在访问它,从而带来滑稽的结果。不过,在包装器类中您无能为力。

顺便说一句,您可以使用ConcurrentHashMap而不是使用同步包装器,这将避免大多数情况下的同步(以更多的内存为代价)。它还提供了许多可以替换调用序列的方法,例如getOrPut();它是编写高性能多线程代码的强大工具。