C# 在ASP.NET核心Web Api中用联锁的.Exchange(ref oldValue,newValue)替换不可变的数据结构安全吗
我有一个api,它是地理坐标请求的终点。这意味着用户可以搜索他们所在区域的特定位置。同时,可以添加新的位置。为了使查询尽可能快,我想我应该使R-树保持不变。也就是说,R-树中没有锁,因为多个线程可以同时读取,而没有争用条件。收集更新,如果收集了100个更新,我想创建一个新的R树并替换旧的R树。现在我的问题是如何做到最好 我有一个SearchService,它存储为单音,并有一个R树作为私有实例 在我的Startup.cs中C# 在ASP.NET核心Web Api中用联锁的.Exchange(ref oldValue,newValue)替换不可变的数据结构安全吗,c#,asp.net-core,.net-core,atomic,C#,Asp.net Core,.net Core,Atomic,我有一个api,它是地理坐标请求的终点。这意味着用户可以搜索他们所在区域的特定位置。同时,可以添加新的位置。为了使查询尽可能快,我想我应该使R-树保持不变。也就是说,R-树中没有锁,因为多个线程可以同时读取,而没有争用条件。收集更新,如果收集了100个更新,我想创建一个新的R树并替换旧的R树。现在我的问题是如何做到最好 我有一个SearchService,它存储为单音,并有一个R树作为私有实例 在我的Startup.cs中 services.AddSingleton<ISearchServ
services.AddSingleton<ISearchService, SearchService>();
services.AddSingleton();
ISearchService.cs
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);
}
}
公共接口ISearchService
{
IEnumerable Get(RTreeQuery);
无效更新(IEnumerable数据);
}
SearchService.cs
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);
}
}
公共类搜索服务:ISearchService
{
私有RTree-RTree;
公共IEnumerable Get(RTreeQuery查询)
{
返回rTree.Get(查询);
}
公共无效更新(IEnumerable数据)
{
var newTree=新的RTree(数据);
联锁交换(参考rTree、newTree);
}
}
我的问题是,如果我用Interlock.exchange()交换引用,操作是原子的,应该没有竞争条件。但是,如果线程仍然使用旧实例来处理其请求,会发生什么呢。垃圾收集器是否会在线程仍然访问旧实例时删除它?毕竟,不再有对旧实例的引用
我对这个话题比较陌生,所以欢迎任何帮助。谢谢你的支持 对引用的读写是原子的,这意味着不会有对齐问题。然而,它们可能是陈腐的
CLI规范第12.6.6节
除非有明确的布局控制(参见分区II(控制实例
布局)用于更改默认行为,数据元素编号
大于自然字号(本机int的大小)的应为
正确对齐。对象引用应视为
以本机字号存储
关于GC,您的树在运行Get
时不会被垃圾收集
总之,就引用原子性而言,您的方法是线程安全的,您还可以使用
更新
方法并安全地覆盖引用,而不需要联锁。Exchange
。当前实现中可能出现的最糟糕情况是,您只得到了一个陈旧的树,您提到的树不是问题。@MichaelRandall感谢您的评论。目前,所有线程都使用同一个SearchService实例,因此在同一个R树实例上。你对如何解决这样的问题有什么建议吗?如果线程使用过时的版本就可以了。但是我不想为每个请求构造R树。@MichaelRandall这样垃圾收集器或其他东西就不会有问题了?如果你喜欢,你可以把它作为一个答案,我会接受:)。非常感谢你的帮助@MichaelRandall不想惹你生气,但是如果你有时间,你仍然可以回答这个问题,这样其他有类似问题的人就可以马上得到解决方案。