使用 Kotlin 的地图委托同步对可变字段的访问
Synchronize access to mutable fields with Kotlin's map delegation
此实现是否可以安全地同步对 public fields/properties 的访问?
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
...
}
大部分。
因为底层映射 仅 可通过同步包装器访问,所以您不会遇到由单个调用引起的任何问题,例如同步获取 and/or 放置(这是竞争条件的主要原因):只有一个线程可以进行这样的调用,Java 内存模型确保结果对所有线程都是可见的。
您可能有涉及调用序列的竞争条件,例如遍历映射,或check followed by a modify ,如果可以在两者之间修改地图。 (这种问题甚至可能发生在单个线程上。)但只要您 class 的其余部分避免此类序列,并且不泄漏对地图的引用,您就安全了。
并且因为类型 Long
、String
和 Date
是不可变的,所以修改它们的内容不会有任何问题。
不过, 与 Any
参数有关。如果它存储例如一个 StringBuilder,一个线程可能正在修改它的内容,而另一个线程正在访问它,结果很滑稽。不过,在包装器 class 中您无能为力。
顺便说一下,您可以使用 ConcurrentHashMap
, which would avoid the synchronisation in most cases (at the cost of a bit more memory). It also provides many methods which can replace call sequences, such as getOrPut()
;而不是使用同步包装器;它是编写 high-performance 多线程代码的非常强大的工具。
此实现是否可以安全地同步对 public fields/properties 的访问?
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
...
}
大部分。
因为底层映射 仅 可通过同步包装器访问,所以您不会遇到由单个调用引起的任何问题,例如同步获取 and/or 放置(这是竞争条件的主要原因):只有一个线程可以进行这样的调用,Java 内存模型确保结果对所有线程都是可见的。
您可能有涉及调用序列的竞争条件,例如遍历映射,或check followed by a modify ,如果可以在两者之间修改地图。 (这种问题甚至可能发生在单个线程上。)但只要您 class 的其余部分避免此类序列,并且不泄漏对地图的引用,您就安全了。
并且因为类型 Long
、String
和 Date
是不可变的,所以修改它们的内容不会有任何问题。
不过, 与 Any
参数有关。如果它存储例如一个 StringBuilder,一个线程可能正在修改它的内容,而另一个线程正在访问它,结果很滑稽。不过,在包装器 class 中您无能为力。
顺便说一下,您可以使用 ConcurrentHashMap
, which would avoid the synchronisation in most cases (at the cost of a bit more memory). It also provides many methods which can replace call sequences, such as getOrPut()
;而不是使用同步包装器;它是编写 high-performance 多线程代码的非常强大的工具。