我有一个WS,它返回有关交易代码的信息。我想在本地缓存WS的结果。 WS查找应该针对不同的符号同时执行,但是对于每个不同的符号,一次只能查找1次。我似乎无法做到这两件事。
这是我正在尝试的锁定的简单版本:
private readonly ReaderWriterLockSlim _cacheLock = new ReaderWriterLockSlim();
private readonly ConcurrentDictionary<string, object> _symbolLock = new ConcurrentDictionary<string, object>();
private readonly MemoryCache _cache = MemoryCache.Default;
public TradingItem GetLinking(string symbol)
{
lock (_symbolLock.GetOrAdd(symbol, new object()))
{
_cacheLock.EnterUpgradeableReadLock();
try
{
if (_cache.Contains(symbol))
{
return _cache.GetCacheItem(symbol);
}
TradingItem item = _resolverService.getLinking(symbol);
_cacheLock.EnterWriteLock();
try
{
_cache.Set(symbol, item, new CacheItemPolicy());
return item;
}
finally
{
_cacheLock.ExitWriteLock();
}
}
finally
{
_cacheLock.ExitUpgradeableReadLock();
}
}
}
作为一方,这看起来很奇怪,但似乎在单元测试中做了我想要的事情:
lock (_symbolLock.GetOrAdd(symbol, new object()))
我的问题是,
如何使WS调用_resolverService.getLinking(symbol)
并发?不同的符号目前受到限制。
谢谢!
答案 0 :(得分:0)
只需在进入写锁定之前执行调用。该代码不使用缓存,因此它不需要与该方法调用的其他缓存访问同步,并且您已经与对同一符号的任何其他调用同步,因此只要你只需要阻止对同一个符号的并发调用,你就已经设置为在获取写锁之前只移动那一行代码。
这当然假设_resolverService
能够同时获得不同符号的链接。如果不是,则不能同时执行它们。
您的代码也禁止任何并发性,因为您只使用可升级的读锁,而不是读锁,其中只能有一个并发的可升级读卡器。您需要有常规的读锁才能实现并发,并且为了确保您的代码没有死锁,您需要确保写操作在读锁之外。