如何解决对于更新不依赖于先前值的不可变集合,是否有任何理由更喜欢 Interlocked 而不是 volatile?
我注意到在讨论不可变集合的问题中(例如 What is the preferred method of updating a reference to an immutable object?)
建议使用 Interlocked
(或更好的 ImmutableInterlocked
)。这样做的原因似乎是针对 CAS,因为在大多数情况下,不可变集合会根据其先前的值进行更新。但是,假设我有一些类包装了一个不可变集合,我希望可以同时访问它并且新值不依赖于旧值,那么使用 Interlocked
仍然是首选吗?换句话说,我有什么理由更喜欢这个:
public class Data {
private ImmutableList<string> values;
public ImmutableList<string> Read() {
return Interlocked.CompareExchange(ref values,null,null);
}
public void Write(IEnumerable<string> update) {
//some arbitrary transformation that doesn't use values at all
var newValues = update.Select(x => x + "-update").ToImmutableList();
Interlocked.Exchange(ref values,newValues);
}
}
在此之上:
public class Data {
private volatile ImmutableList<string> values;
public ImmutableList<string> Read() {
return values;
}
public void Write(IEnumerable<string> update) {
//some arbitrary transformation that doesn't use values at all
var newValues = update.Select(x => x + "-update").ToImmutableList();
values = newValues;
}
}
解决方法
不,没有理由。将 values
字段标记为 volatile
足以确保所有线程都能看到存储在该字段中的最新值。
不过应该注意的是,不可变集合,尤其是 ImmutableList<T>
的强大之处在于它们能够在每次更新时重用大部分内部状态。大多数如果它们被实现为二叉树,并且更新它们会导致替换树中的一些节点。如果你每次都更新整个集合,那么你就会得到这种方法的所有缺点(开销、内存大小),而没有它的优点(内存可重用性)。
此规则的例外是 ImmutableArray<T>
结构,它在内部实现为一个简单数组。它不提供可重用性,但性能非常好,因此它似乎非常适合您的情况。为了克服它是值类型的事实,您可以将它存储在类型为 IImmutableList<T>
的字段中。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。