C#只锁定不同的对象(而不是线程)?

时间:2017-05-03 17:57:19

标签: c# multithreading web-services locking

我有一个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)并发?不同的符号目前受到限制。

谢谢!

1 个答案:

答案 0 :(得分:0)

只需在进入写锁定之前执行调用。该代码不使用缓存,因此它不需要与该方法调用的其他缓存访问同步,并且您已经与对同一符号的任何其他调用同步,因此只要你只需要阻止对同一个符号的并发调用,你就已经设置为在获取写锁之前只移动那一行代码。

这当然假设_resolverService能够同时获得不同符号的链接。如果不是,则不能同时执行它们。

您的代码也禁止任何并发性,因为您只使用可升级的读锁,而不是读锁,其中只能有一个并发的可升级读卡器。您需要有常规的读锁才能实现并发,并且为了确保您的代码没有死锁,您需要确保写操作在读锁之外。