锁字典不断增长,关于如何清理的想法?

时间:2011-04-28 14:49:02

标签: c# data-structures locking memory-management race-condition

我有一个基于网络的订单系统。

  • 物品限时,Y小时发售
  • 每个项目仅允许X个订单

保持每件商品的订单< = X我正在使用这种锁定机制。

private static Dictionary<Guid, Object> PurchaseLockDictionary = null;

private static object GetLock(Guid itemId)
    {
        if (!PurchaseLockDictionary.ContainsKey(itemId))
        {
            PurchaseLockDictionary.Add(itemId, new object());
        }
        return PurchaseLockDictionary[itemId];
    }

购买看起来像这样:

public static Order Purchase(Buyer buyer, OrderItem item)
    {
        Order order;
        try
        {
            lock (GetLock(item.Id))
            {
                // order stuff like counting current amount of orders, buyer validity etc
            }
        } catch (Exception e) {
            // Exception stuff
        }
        return order;
    }

现在,我的问题是,如何保持我的锁定机制(Dictionary对象)不会超出比例?目前我们出于其他原因每周重启服务器,但我不希望代码依赖此类行为。

是否有其他更适合此锁定机制的数据结构?或者是否有一种智能的方法来查找和清除字典中的旧条目?非常欢迎您的想法!

3 个答案:

答案 0 :(得分:2)

using (var locker = new PurchaseLocker(item.Id))
{
    // order stuff like counting current amount of orders, buyer validity etc
}

// ...

public sealed class PurchaseLocker : IDisposable
{
    private static readonly object _bigLock = new object();
    private static readonly Dictionary<Guid, LockToken> _lockMap = new Dictionary<Guid, LockToken>();
    private readonly Guid _itemId;

    public PurchaseLocker(Guid itemId)
    {
        _itemId = itemId;

        LockToken miniLock;
        lock (_bigLock)
        {
            if (!_lockMap.TryGetValue(itemId, out miniLock))
            {
                miniLock = new LockToken();
                _lockMap.Add(itemId, miniLock);
            }
            miniLock.Count++;
        }
        Monitor.Enter(miniLock);
    }

    public void Dispose()
    {
        lock (_bigLock)
        {
            LockToken miniLock = _lockMap[_itemId];
            miniLock.Count--;
            if (miniLock.Count == 0)
                _lockMap.Remove(_itemId);

            Monitor.Exit(miniLock);
        }
    }

    private sealed class LockToken
    {
        public int Count;
    }
}

答案 1 :(得分:1)

听起来您想要使用缓存解决方案,该解决方案会使未经常使用/访问的项目失效。如果是这样,那么你应该看看System.Runtime.Caching。您可以将项目添加到缓存并设置其到期策略等。

答案 2 :(得分:1)

如果您在多线程程序中使用它,那么您将遇到麻烦。 Dictionary不是线程安全的。请考虑使用ConcurrentDictionary代替。

对于您的商品,我假设您每次订购一个订单时都会增加订单数量。如果该商品的订单数量达到最大值,或者该商品特殊销售时,您是否只能使用Purchase方法从字典中删除该商品?