锁字典不断增长,请问如何清理?

发布于 2024-11-04 01:58:22 字数 1019 浏览 1 评论 0原文

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

  • 商品的时间有限,促销 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;
    }

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

还有其他的数据结构更适合这种锁定机制吗?或者是否有一种聪明的方法来查找和清理词典中的旧条目?非常欢迎提出想法!

I have a web based order system for items.

  • Items are very time limited, on sale for Y hours
  • Each item allow only X orders

To keep the orders per item <= X I'm using this locking mechanism.

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

And the purchase looks like this:

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

Now, my question is, how do I keep my locking mechanism (the Dictionary object) from growing out of proportions? Currently we perform a weekly reboot of the server for other reasons, but I do not want the code to rely on such behavior.

Is there another data structure that is more suitable for this locking mechanism? Or is there a smart way of find and clean old entries in the Dictionary? Ideas are very welcome!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

谷夏 2024-11-11 01:58:22
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;
    }
}
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;
    }
}
赠佳期 2024-11-11 01:58:22

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

It sounds like you want to use a cache solution which will expire items that are not used/accessed frequently. If so then you should take a look at System.Runtime.Caching. You can add items to the cache and set their expiry policy etc.

素食主义者 2024-11-11 01:58:22

如果你在多线程程序中使用它,你就会遇到麻烦。 字典不是线程安全的。考虑使用 ConcurrentDictionary 代替。

对于您的商品,我假设每次有人订购一件商品时您都会增加订单计数。难道您不能让 Purchase 方法在该商品的订单数达到最大值或该商品变得特别时从字典中删除该商品吗?

If you're using that in a multi-threaded program, you're going to have trouble. Dictionary is not thread-safe. Consider using ConcurrentDictionary instead.

For your items, I assume you're incrementing an order count every time somebody orders one. Can't you just have the Purchase method remove the item from the dictionary when that item's order count gets to the maximum, or when the item goes off special?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文