当用户输入query
搜索:
如果用户执行的搜索时间为10秒,并且他们不耐烦地刷新页面,我们就不希望它再次启动查询。这应该被锁定。
但是,如果运行昂贵的查询,我们并不想锁定执行较便宜搜索的其他用户。
要解决这个问题,我需要多个锁。
这就是我目前实施的方式:
private static readonly object MasterManualSearchLock = new object();
private static readonly Dictionary<string, object> ManualSearchLocks = new Dictionary<string, object>();
/// <summary>
/// Search the manual
/// </summary>
public static SearchResponse DoSearch(string query, Manual forManual)
{
var tokens = Search.Functions.TokeniseSearchQuery(query);
var tokenHash = Search.Functions.GetUniqueHashOfTokens(tokens);
var cacheIndex = Settings.CachePrefix + "SavedManualSearch_" + tokenHash;
var context = HttpContext.Current;
if (context.Cache[cacheIndex] == null)
{
// Create lock if it doesn't exist
if (!ManualSearchLocks.ContainsKey(tokenHash))
{
lock (MasterManualSearchLock)
{
if (!ManualSearchLocks.ContainsKey(tokenHash))
{
ManualSearchLocks.Add(tokenHash, new object());
}
}
}
lock (ManualSearchLocks[tokenHash])
{
if (context.Cache[cacheIndex] == null)
{
var searchResponse = new SearchResponse(tokens, forManual, query);
context.Cache.Add(cacheIndex, searchResponse, null, DateTime.Now.AddMinutes(Settings.Search.SearchResultsAbsoluteTimeoutMins), Cache.NoSlidingExpiration, CacheItemPriority.BelowNormal, null);
}
ManualSearchLocks.Remove(tokenHash);
}
}
return (SearchResponse)context.Cache[cacheIndex];
}
答案 0 :(得分:0)
您同时使用ManualSearchLocks
是不安全的,ConcurrentDictionary
是一个很好的替代品。不,只是从字典中读取是不安全的,因为没有记录是安全的。
我将Lazy<T>
放入缓存中。可能会生成多个这样的惰性实例,但只有一个会实现。想要访问特定密钥的所有线程都将调用Lazy.Value
并自动进行同步。一旦实际&#34;搜索&#34;将被执行。
根据您访问缓存的方式,可能存在一个小的竞争条件,允许执行多个惰性实例。在你的情况下,这可能不是什么大问题。