[英]Is it safe to replace immutable data structure with Interlocked.Exchange(ref oldValue, newValue) in ASP.NET Core Web-Api
我有一个 api,它是地理坐标请求的端点。 这意味着用户可以搜索他们所在地区的特定位置。 同时可以添加新的位置。 为了尽可能快地进行查询,我想我会让 R 树不可更改。 也就是说,R-Tree 中没有锁,因为多个线程可以同时读取,没有竞争条件。 收集更新,如果收集到 100 个更新,我想创建一个新的 R-Tree 并替换旧的。 现在我的问题是如何做到最好?
我有一个 SearchService,它存储为单音,并有一个 R-Tree 作为私有实例。
在我的 Startup.cs 中
services.AddSingleton<ISearchService, SearchService>();
搜索服务
public interface ISearchService
{
IEnumerable<GeoLocation> Get(RTreeQuery query);
void Update(IEnumerable<GeoLocation> data);
}
搜索服务
public class SearchService : ISearchService
{
private RTree rTree;
public IEnumerable<GeoLocation> Get(RTreeQuery query)
{
return rTree.Get(query);
}
public void Update(IEnumerable<GeoLocation> data)
{
var newTree = new RTree(data);
Interlocked.Exchange<RTree>(ref rTree, newTree);
}
}
我的问题是,如果我用 Interlock.Exchange() 交换引用,操作是原子的,应该没有竞争条件。 但是如果线程仍然使用旧实例来处理它们的请求会发生什么。 是不是垃圾收集器在线程仍然访问旧实例时删除了它? 毕竟,不再有对旧实例的引用。
我对这个话题比较陌生,所以欢迎任何帮助。 谢谢您的支持!
对引用的读取和写入是原子的,这意味着不会有对齐问题。 但是,它们可能是陈旧的。
CLI 规范的第 12.6.6 节
除非使用显式布局控制(参见第 II 部分(控制实例布局))来改变默认行为,否则不大于自然字大小(本机 int 的大小)的数据元素应正确对齐。 对象引用应被视为以本地字大小存储。
关于 GC,您的树在运行Get
时不会被垃圾收集。
所以总而言之,就引用原子性而言,您的方法是线程安全的,您还可以使用Update
方法并安全地覆盖引用,不需要Interlocked.Exchange
。 您当前的实现可能发生的最糟糕的情况是您只会得到一个您提到的陈旧树,这不是问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.