锁字典不断增长,关于如何清理的意见

本文关键字:于如何 字典 不断增长 | 更新日期: 2023-09-27 17:53:49

我有一个基于web的物品订购系统。

  • 商品限时出售,限时销售
  • 每个项目只允许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;
    }

现在,我的问题是,我如何保持我的锁定机制(字典对象)增长不成比例?目前,由于其他原因,我们每周重启一次服务器,但我不希望代码依赖于这种行为。

是否有另一种数据结构更适合这种锁定机制?或者是否有一种聪明的方法来查找和清除字典中的旧条目?非常欢迎有想法的人!

锁字典不断增长,关于如何清理的意见

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;
    }
}

听起来你想使用一个缓存解决方案,它将过期不经常使用/访问的项目。如果是这样,那么您应该看看System.Runtime.Caching。您可以向缓存中添加条目并设置它们的过期策略等。

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

对于您的商品,我假设您在每次有人订购时增加订单计数。难道不能让Purchase方法在项目的订单计数达到最大值时,或者项目异常时,从字典中删除该项目吗?